196 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			196 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file
							 | 
						||
| 
								 | 
							
								 * Attaches behaviors for the Comment module's "X new comments" link.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * May only be loaded for authenticated users, with the History module
							 | 
						||
| 
								 | 
							
								 * installed.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function ($, Drupal, drupalSettings) {
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Hides a "new comment" element.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @param {jQuery} $placeholder
							 | 
						||
| 
								 | 
							
								   *   The placeholder element of the new comment link.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @return {jQuery}
							 | 
						||
| 
								 | 
							
								   *   The placeholder element passed in as a parameter.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function hide($placeholder) {
							 | 
						||
| 
								 | 
							
								    return (
							 | 
						||
| 
								 | 
							
								      $placeholder
							 | 
						||
| 
								 | 
							
								        // Find the parent <li>.
							 | 
						||
| 
								 | 
							
								        .closest('.comment-new-comments')
							 | 
						||
| 
								 | 
							
								        // Find the preceding <li>, if any, and give it the 'last' class.
							 | 
						||
| 
								 | 
							
								        .prev()
							 | 
						||
| 
								 | 
							
								        .addClass('last')
							 | 
						||
| 
								 | 
							
								        // Go back to the parent <li> and hide it.
							 | 
						||
| 
								 | 
							
								        .end()
							 | 
						||
| 
								 | 
							
								        .hide()
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Removes a "new comment" element.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @param {jQuery} $placeholder
							 | 
						||
| 
								 | 
							
								   *   The placeholder element of the new comment link.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function remove($placeholder) {
							 | 
						||
| 
								 | 
							
								    hide($placeholder).remove();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Shows a "new comment" element.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @param {jQuery} $placeholder
							 | 
						||
| 
								 | 
							
								   *   The placeholder element of the new comment link.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @return {jQuery}
							 | 
						||
| 
								 | 
							
								   *   The placeholder element passed in as a parameter.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function show($placeholder) {
							 | 
						||
| 
								 | 
							
								    return (
							 | 
						||
| 
								 | 
							
								      $placeholder
							 | 
						||
| 
								 | 
							
								        // Find the parent <li>.
							 | 
						||
| 
								 | 
							
								        .closest('.comment-new-comments')
							 | 
						||
| 
								 | 
							
								        // Find the preceding <li>, if any, and remove its 'last' class, if any.
							 | 
						||
| 
								 | 
							
								        .prev()
							 | 
						||
| 
								 | 
							
								        .removeClass('last')
							 | 
						||
| 
								 | 
							
								        // Go back to the parent <li> and show it.
							 | 
						||
| 
								 | 
							
								        .end()
							 | 
						||
| 
								 | 
							
								        .show()
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Processes new comment links and adds appropriate text in relevant cases.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @param {Array.<Element>} placeholders
							 | 
						||
| 
								 | 
							
								   *   The placeholder elements of the current page.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function processNodeNewCommentLinks(placeholders) {
							 | 
						||
| 
								 | 
							
								    // Figure out which placeholders need the "x new comments" links.
							 | 
						||
| 
								 | 
							
								    const $placeholdersToUpdate = {};
							 | 
						||
| 
								 | 
							
								    let fieldName = 'comment';
							 | 
						||
| 
								 | 
							
								    let $placeholder;
							 | 
						||
| 
								 | 
							
								    placeholders.forEach((placeholder) => {
							 | 
						||
| 
								 | 
							
								      $placeholder = $(placeholder);
							 | 
						||
| 
								 | 
							
								      const timestamp = parseInt(
							 | 
						||
| 
								 | 
							
								        $placeholder.attr('data-history-node-last-comment-timestamp'),
							 | 
						||
| 
								 | 
							
								        10,
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      fieldName = $placeholder.attr('data-history-node-field-name');
							 | 
						||
| 
								 | 
							
								      const nodeID = $placeholder
							 | 
						||
| 
								 | 
							
								        .closest('[data-history-node-id]')
							 | 
						||
| 
								 | 
							
								        .attr('data-history-node-id');
							 | 
						||
| 
								 | 
							
								      const lastViewTimestamp = Drupal.history.getLastRead(nodeID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Queue this placeholder's "X new comments" link to be downloaded from
							 | 
						||
| 
								 | 
							
								      // the server.
							 | 
						||
| 
								 | 
							
								      if (timestamp > lastViewTimestamp) {
							 | 
						||
| 
								 | 
							
								        $placeholdersToUpdate[nodeID] = $placeholder;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      // No "X new comments" link necessary; remove it from the DOM.
							 | 
						||
| 
								 | 
							
								      else {
							 | 
						||
| 
								 | 
							
								        remove($placeholder);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Perform an AJAX request to retrieve node view timestamps.
							 | 
						||
| 
								 | 
							
								    const nodeIDs = Object.keys($placeholdersToUpdate);
							 | 
						||
| 
								 | 
							
								    if (nodeIDs.length === 0) {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /**
							 | 
						||
| 
								 | 
							
								     * Renders the "X new comments" links.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * Either use the data embedded in the page or perform an AJAX request to
							 | 
						||
| 
								 | 
							
								     * retrieve the same data.
							 | 
						||
| 
								 | 
							
								     *
							 | 
						||
| 
								 | 
							
								     * @param {object} results
							 | 
						||
| 
								 | 
							
								     *   Data about new comment links indexed by nodeID.
							 | 
						||
| 
								 | 
							
								     */
							 | 
						||
| 
								 | 
							
								    function render(results) {
							 | 
						||
| 
								 | 
							
								      Object.keys(results || {}).forEach((nodeID) => {
							 | 
						||
| 
								 | 
							
								        if ($placeholdersToUpdate.hasOwnProperty(nodeID)) {
							 | 
						||
| 
								 | 
							
								          const $placeholderItem = $placeholdersToUpdate[nodeID];
							 | 
						||
| 
								 | 
							
								          const result = results[nodeID];
							 | 
						||
| 
								 | 
							
								          $placeholderItem[0].textContent = Drupal.formatPlural(
							 | 
						||
| 
								 | 
							
								            result.new_comment_count,
							 | 
						||
| 
								 | 
							
								            '1 new comment',
							 | 
						||
| 
								 | 
							
								            '@count new comments',
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								          $placeholderItem
							 | 
						||
| 
								 | 
							
								            .attr('href', result.first_new_comment_link)
							 | 
						||
| 
								 | 
							
								            .removeClass('hidden');
							 | 
						||
| 
								 | 
							
								          show($placeholderItem);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (drupalSettings.comment?.newCommentsLinks) {
							 | 
						||
| 
								 | 
							
								      render(drupalSettings.comment.newCommentsLinks.node[fieldName]);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      $.ajax({
							 | 
						||
| 
								 | 
							
								        url: Drupal.url('comments/render_new_comments_node_links'),
							 | 
						||
| 
								 | 
							
								        type: 'POST',
							 | 
						||
| 
								 | 
							
								        data: { 'node_ids[]': nodeIDs, field_name: fieldName },
							 | 
						||
| 
								 | 
							
								        dataType: 'json',
							 | 
						||
| 
								 | 
							
								        success: render,
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Render "X new comments" links wherever necessary.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @type {Drupal~behavior}
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @prop {Drupal~behaviorAttach} attach
							 | 
						||
| 
								 | 
							
								   *   Attaches new comment links behavior.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  Drupal.behaviors.nodeNewCommentsLink = {
							 | 
						||
| 
								 | 
							
								    attach(context) {
							 | 
						||
| 
								 | 
							
								      // Collect all "X new comments" node link placeholders (and their
							 | 
						||
| 
								 | 
							
								      // corresponding node IDs) newer than 30 days ago that have not already
							 | 
						||
| 
								 | 
							
								      // been read after their last comment timestamp.
							 | 
						||
| 
								 | 
							
								      const nodeIDs = [];
							 | 
						||
| 
								 | 
							
								      const placeholders = once(
							 | 
						||
| 
								 | 
							
								        'history',
							 | 
						||
| 
								 | 
							
								        '[data-history-node-last-comment-timestamp]',
							 | 
						||
| 
								 | 
							
								        context,
							 | 
						||
| 
								 | 
							
								      ).filter((placeholder) => {
							 | 
						||
| 
								 | 
							
								        const $placeholder = $(placeholder);
							 | 
						||
| 
								 | 
							
								        const lastCommentTimestamp = parseInt(
							 | 
						||
| 
								 | 
							
								          $placeholder.attr('data-history-node-last-comment-timestamp'),
							 | 
						||
| 
								 | 
							
								          10,
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        const nodeID = $placeholder
							 | 
						||
| 
								 | 
							
								          .closest('[data-history-node-id]')
							 | 
						||
| 
								 | 
							
								          .attr('data-history-node-id');
							 | 
						||
| 
								 | 
							
								        if (Drupal.history.needsServerCheck(nodeID, lastCommentTimestamp)) {
							 | 
						||
| 
								 | 
							
								          nodeIDs.push(nodeID);
							 | 
						||
| 
								 | 
							
								          // Hide this placeholder link until it is certain we'll need it.
							 | 
						||
| 
								 | 
							
								          hide($placeholder);
							 | 
						||
| 
								 | 
							
								          return true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Remove this placeholder link from the DOM because we won't need it.
							 | 
						||
| 
								 | 
							
								        remove($placeholder);
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (placeholders.length === 0) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Perform an AJAX request to retrieve node read timestamps.
							 | 
						||
| 
								 | 
							
								      Drupal.history.fetchTimestamps(nodeIDs, () => {
							 | 
						||
| 
								 | 
							
								        processNodeNewCommentLinks(placeholders);
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								})(jQuery, Drupal, drupalSettings);
							 |