Chris@0: /** Chris@0: * @file Chris@0: * Attaches behaviors for the Comment module's "new" indicator. Chris@0: * Chris@0: * May only be loaded for authenticated users, with the History module Chris@0: * installed. Chris@0: */ Chris@0: Chris@17: (function($, Drupal, window) { Chris@0: /** Chris@0: * Processes the markup for "new comment" indicators. Chris@0: * Chris@0: * @param {jQuery} $placeholders Chris@0: * The elements that should be processed. Chris@0: */ Chris@0: function processCommentNewIndicators($placeholders) { Chris@0: let isFirstNewComment = true; Chris@0: const newCommentString = Drupal.t('new'); Chris@0: let $placeholder; Chris@0: Chris@0: $placeholders.each((index, placeholder) => { Chris@0: $placeholder = $(placeholder); Chris@17: const timestamp = parseInt( Chris@17: $placeholder.attr('data-comment-timestamp'), Chris@17: 10, Chris@17: ); Chris@0: const $node = $placeholder.closest('[data-history-node-id]'); Chris@0: const nodeID = $node.attr('data-history-node-id'); Chris@0: const lastViewTimestamp = Drupal.history.getLastRead(nodeID); Chris@0: Chris@0: if (timestamp > lastViewTimestamp) { Chris@0: // Turn the placeholder into an actual "new" indicator. Chris@0: const $comment = $(placeholder) Chris@0: .removeClass('hidden') Chris@0: .text(newCommentString) Chris@0: .closest('.js-comment') Chris@0: // Add 'new' class to the comment, so it can be styled. Chris@0: .addClass('new'); Chris@0: Chris@0: // Insert "new" anchor just before the "comment-" anchor if Chris@0: // this is the first new comment in the DOM. Chris@0: if (isFirstNewComment) { Chris@0: isFirstNewComment = false; Chris@0: $comment.prev().before(''); Chris@0: // If the URL points to the first new comment, then scroll to that Chris@0: // comment. Chris@0: if (window.location.hash === '#new') { Chris@17: window.scrollTo( Chris@17: 0, Chris@17: $comment.offset().top - Drupal.displace.offsets.top, Chris@17: ); Chris@0: } Chris@0: } Chris@0: } Chris@0: }); Chris@0: } Chris@17: Chris@17: /** Chris@17: * Renders "new" comment indicators wherever necessary. Chris@17: * Chris@17: * @type {Drupal~behavior} Chris@17: * Chris@17: * @prop {Drupal~behaviorAttach} attach Chris@17: * Attaches "new" comment indicators behavior. Chris@17: */ Chris@17: Drupal.behaviors.commentNewIndicator = { Chris@17: attach(context) { Chris@17: // Collect all "new" comment indicator placeholders (and their Chris@17: // corresponding node IDs) newer than 30 days ago that have not already Chris@17: // been read after their last comment timestamp. Chris@17: const nodeIDs = []; Chris@17: const $placeholders = $(context) Chris@17: .find('[data-comment-timestamp]') Chris@17: .once('history') Chris@17: .filter(function() { Chris@17: const $placeholder = $(this); Chris@17: const commentTimestamp = parseInt( Chris@17: $placeholder.attr('data-comment-timestamp'), Chris@17: 10, Chris@17: ); Chris@17: const nodeID = $placeholder Chris@17: .closest('[data-history-node-id]') Chris@17: .attr('data-history-node-id'); Chris@17: if (Drupal.history.needsServerCheck(nodeID, commentTimestamp)) { Chris@17: nodeIDs.push(nodeID); Chris@17: return true; Chris@17: } Chris@17: Chris@17: return false; Chris@17: }); Chris@17: Chris@17: if ($placeholders.length === 0) { Chris@17: return; Chris@17: } Chris@17: Chris@17: // Fetch the node read timestamps from the server. Chris@17: Drupal.history.fetchTimestamps(nodeIDs, () => { Chris@17: processCommentNewIndicators($placeholders); Chris@17: }); Chris@17: }, Chris@17: }; Chris@17: })(jQuery, Drupal, window);