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