Chris@0
|
1 /**
|
Chris@0
|
2 * @file
|
Chris@0
|
3 * Attaches behaviors for the Comment module's "X new comments" link.
|
Chris@0
|
4 *
|
Chris@0
|
5 * May only be loaded for authenticated users, with the History module
|
Chris@0
|
6 * installed.
|
Chris@0
|
7 */
|
Chris@0
|
8
|
Chris@17
|
9 (function($, Drupal, drupalSettings) {
|
Chris@0
|
10 /**
|
Chris@0
|
11 * Hides a "new comment" element.
|
Chris@0
|
12 *
|
Chris@0
|
13 * @param {jQuery} $placeholder
|
Chris@0
|
14 * The placeholder element of the new comment link.
|
Chris@0
|
15 *
|
Chris@0
|
16 * @return {jQuery}
|
Chris@0
|
17 * The placeholder element passed in as a parameter.
|
Chris@0
|
18 */
|
Chris@0
|
19 function hide($placeholder) {
|
Chris@17
|
20 return (
|
Chris@17
|
21 $placeholder
|
Chris@17
|
22 // Find the parent <li>.
|
Chris@17
|
23 .closest('.comment-new-comments')
|
Chris@17
|
24 // Find the preceding <li>, if any, and give it the 'last' class.
|
Chris@17
|
25 .prev()
|
Chris@17
|
26 .addClass('last')
|
Chris@17
|
27 // Go back to the parent <li> and hide it.
|
Chris@17
|
28 .end()
|
Chris@17
|
29 .hide()
|
Chris@17
|
30 );
|
Chris@0
|
31 }
|
Chris@0
|
32
|
Chris@0
|
33 /**
|
Chris@0
|
34 * Removes a "new comment" element.
|
Chris@0
|
35 *
|
Chris@0
|
36 * @param {jQuery} $placeholder
|
Chris@0
|
37 * The placeholder element of the new comment link.
|
Chris@0
|
38 */
|
Chris@0
|
39 function remove($placeholder) {
|
Chris@0
|
40 hide($placeholder).remove();
|
Chris@0
|
41 }
|
Chris@0
|
42
|
Chris@0
|
43 /**
|
Chris@0
|
44 * Shows a "new comment" element.
|
Chris@0
|
45 *
|
Chris@0
|
46 * @param {jQuery} $placeholder
|
Chris@0
|
47 * The placeholder element of the new comment link.
|
Chris@0
|
48 *
|
Chris@0
|
49 * @return {jQuery}
|
Chris@0
|
50 * The placeholder element passed in as a parameter.
|
Chris@0
|
51 */
|
Chris@0
|
52 function show($placeholder) {
|
Chris@17
|
53 return (
|
Chris@17
|
54 $placeholder
|
Chris@17
|
55 // Find the parent <li>.
|
Chris@17
|
56 .closest('.comment-new-comments')
|
Chris@17
|
57 // Find the preceding <li>, if any, and remove its 'last' class, if any.
|
Chris@17
|
58 .prev()
|
Chris@17
|
59 .removeClass('last')
|
Chris@17
|
60 // Go back to the parent <li> and show it.
|
Chris@17
|
61 .end()
|
Chris@17
|
62 .show()
|
Chris@17
|
63 );
|
Chris@0
|
64 }
|
Chris@0
|
65
|
Chris@0
|
66 /**
|
Chris@0
|
67 * Processes new comment links and adds appropriate text in relevant cases.
|
Chris@0
|
68 *
|
Chris@0
|
69 * @param {jQuery} $placeholders
|
Chris@0
|
70 * The placeholder elements of the current page.
|
Chris@0
|
71 */
|
Chris@0
|
72 function processNodeNewCommentLinks($placeholders) {
|
Chris@0
|
73 // Figure out which placeholders need the "x new comments" links.
|
Chris@0
|
74 const $placeholdersToUpdate = {};
|
Chris@0
|
75 let fieldName = 'comment';
|
Chris@0
|
76 let $placeholder;
|
Chris@0
|
77 $placeholders.each((index, placeholder) => {
|
Chris@0
|
78 $placeholder = $(placeholder);
|
Chris@17
|
79 const timestamp = parseInt(
|
Chris@17
|
80 $placeholder.attr('data-history-node-last-comment-timestamp'),
|
Chris@17
|
81 10,
|
Chris@17
|
82 );
|
Chris@0
|
83 fieldName = $placeholder.attr('data-history-node-field-name');
|
Chris@17
|
84 const nodeID = $placeholder
|
Chris@17
|
85 .closest('[data-history-node-id]')
|
Chris@17
|
86 .attr('data-history-node-id');
|
Chris@0
|
87 const lastViewTimestamp = Drupal.history.getLastRead(nodeID);
|
Chris@0
|
88
|
Chris@0
|
89 // Queue this placeholder's "X new comments" link to be downloaded from
|
Chris@0
|
90 // the server.
|
Chris@0
|
91 if (timestamp > lastViewTimestamp) {
|
Chris@0
|
92 $placeholdersToUpdate[nodeID] = $placeholder;
|
Chris@0
|
93 }
|
Chris@0
|
94 // No "X new comments" link necessary; remove it from the DOM.
|
Chris@0
|
95 else {
|
Chris@0
|
96 remove($placeholder);
|
Chris@0
|
97 }
|
Chris@0
|
98 });
|
Chris@0
|
99
|
Chris@0
|
100 // Perform an AJAX request to retrieve node view timestamps.
|
Chris@0
|
101 const nodeIDs = Object.keys($placeholdersToUpdate);
|
Chris@0
|
102 if (nodeIDs.length === 0) {
|
Chris@0
|
103 return;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * Renders the "X new comments" links.
|
Chris@0
|
108 *
|
Chris@0
|
109 * Either use the data embedded in the page or perform an AJAX request to
|
Chris@0
|
110 * retrieve the same data.
|
Chris@0
|
111 *
|
Chris@0
|
112 * @param {object} results
|
Chris@0
|
113 * Data about new comment links indexed by nodeID.
|
Chris@0
|
114 */
|
Chris@0
|
115 function render(results) {
|
Chris@17
|
116 Object.keys(results || {}).forEach(nodeID => {
|
Chris@14
|
117 if ($placeholdersToUpdate.hasOwnProperty(nodeID)) {
|
Chris@0
|
118 $placeholdersToUpdate[nodeID]
|
Chris@0
|
119 .attr('href', results[nodeID].first_new_comment_link)
|
Chris@17
|
120 .text(
|
Chris@17
|
121 Drupal.formatPlural(
|
Chris@17
|
122 results[nodeID].new_comment_count,
|
Chris@17
|
123 '1 new comment',
|
Chris@17
|
124 '@count new comments',
|
Chris@17
|
125 ),
|
Chris@17
|
126 )
|
Chris@0
|
127 .removeClass('hidden');
|
Chris@0
|
128 show($placeholdersToUpdate[nodeID]);
|
Chris@0
|
129 }
|
Chris@14
|
130 });
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 if (drupalSettings.comment && drupalSettings.comment.newCommentsLinks) {
|
Chris@0
|
134 render(drupalSettings.comment.newCommentsLinks.node[fieldName]);
|
Chris@17
|
135 } else {
|
Chris@0
|
136 $.ajax({
|
Chris@0
|
137 url: Drupal.url('comments/render_new_comments_node_links'),
|
Chris@0
|
138 type: 'POST',
|
Chris@0
|
139 data: { 'node_ids[]': nodeIDs, field_name: fieldName },
|
Chris@0
|
140 dataType: 'json',
|
Chris@0
|
141 success: render,
|
Chris@0
|
142 });
|
Chris@0
|
143 }
|
Chris@0
|
144 }
|
Chris@17
|
145
|
Chris@17
|
146 /**
|
Chris@17
|
147 * Render "X new comments" links wherever necessary.
|
Chris@17
|
148 *
|
Chris@17
|
149 * @type {Drupal~behavior}
|
Chris@17
|
150 *
|
Chris@17
|
151 * @prop {Drupal~behaviorAttach} attach
|
Chris@17
|
152 * Attaches new comment links behavior.
|
Chris@17
|
153 */
|
Chris@17
|
154 Drupal.behaviors.nodeNewCommentsLink = {
|
Chris@17
|
155 attach(context) {
|
Chris@17
|
156 // Collect all "X new comments" node link placeholders (and their
|
Chris@17
|
157 // corresponding node IDs) newer than 30 days ago that have not already
|
Chris@17
|
158 // been read after their last comment timestamp.
|
Chris@17
|
159 const nodeIDs = [];
|
Chris@17
|
160 const $placeholders = $(context)
|
Chris@17
|
161 .find('[data-history-node-last-comment-timestamp]')
|
Chris@17
|
162 .once('history')
|
Chris@17
|
163 .filter(function() {
|
Chris@17
|
164 const $placeholder = $(this);
|
Chris@17
|
165 const lastCommentTimestamp = parseInt(
|
Chris@17
|
166 $placeholder.attr('data-history-node-last-comment-timestamp'),
|
Chris@17
|
167 10,
|
Chris@17
|
168 );
|
Chris@17
|
169 const nodeID = $placeholder
|
Chris@17
|
170 .closest('[data-history-node-id]')
|
Chris@17
|
171 .attr('data-history-node-id');
|
Chris@17
|
172 if (Drupal.history.needsServerCheck(nodeID, lastCommentTimestamp)) {
|
Chris@17
|
173 nodeIDs.push(nodeID);
|
Chris@17
|
174 // Hide this placeholder link until it is certain we'll need it.
|
Chris@17
|
175 hide($placeholder);
|
Chris@17
|
176 return true;
|
Chris@17
|
177 }
|
Chris@17
|
178
|
Chris@17
|
179 // Remove this placeholder link from the DOM because we won't need
|
Chris@17
|
180 // it.
|
Chris@17
|
181 remove($placeholder);
|
Chris@17
|
182 return false;
|
Chris@17
|
183 });
|
Chris@17
|
184
|
Chris@17
|
185 if ($placeholders.length === 0) {
|
Chris@17
|
186 return;
|
Chris@17
|
187 }
|
Chris@17
|
188
|
Chris@17
|
189 // Perform an AJAX request to retrieve node read timestamps.
|
Chris@17
|
190 Drupal.history.fetchTimestamps(nodeIDs, () => {
|
Chris@17
|
191 processNodeNewCommentLinks($placeholders);
|
Chris@17
|
192 });
|
Chris@17
|
193 },
|
Chris@17
|
194 };
|
Chris@17
|
195 })(jQuery, Drupal, drupalSettings);
|