diff --git a/config/install/disqus.settings.yml b/config/install/disqus.settings.yml index 5852b86..7a425f7 100644 --- a/config/install/disqus.settings.yml +++ b/config/install/disqus.settings.yml @@ -15,3 +15,7 @@ advanced: disqus_sso: false disqus_use_site_logo: false disqus_logo: '' + lazy_loading: + status: 0 + method: 'scroll' + class: disqus-lazy-load diff --git a/disqus.module b/disqus.module index 8c0d476..c195b04 100644 --- a/disqus.module +++ b/disqus.module @@ -260,6 +260,11 @@ function disqus_theme() { 'url' => "http://$domain.disqus.com/", ], ], + 'disqus_lazy_load' => [ + 'variables' => [ + 'children' => NULL, + ], + ], ]; } diff --git a/js/disqus.js b/js/disqus.js index 25b7de7..6c4229b 100644 --- a/js/disqus.js +++ b/js/disqus.js @@ -17,7 +17,27 @@ var disqus_config; "use strict"; -Drupal.disqus = {}; +/** +* JS load helper functions. +*/ +Drupal.disqus = { + loadCommentScript: function (shortname) { + // Make the AJAX call to get the Disqus comments. + this.loadScript(shortname, 'embed.js') + }, + loadCountScript: function (shortname) { + // Make the AJAX call to get the number of comments. + this.loadScript(shortname, 'count.js'); + }, + loadScript: function (shortname, scriptName) { + $.ajax({ + type: 'GET', + url: '//' + shortname + '.disqus.com/' + scriptName, + dataType: 'script', + cache: false + }); + } +}; /** * Drupal Disqus behavior. @@ -69,13 +89,30 @@ Drupal.behaviors.disqus = { } }; - // Make the AJAX call to get the Disqus comments. - jQuery.ajax({ - type: 'GET', - url: '//' + disqus_shortname + '.disqus.com/embed.js', - dataType: 'script', - cache: false - }); + if (settings.disqus.lazyLoadMethod || '') { + switch (settings.disqus.lazyLoadMethod) { + case 'click': + $('.' + (settings.disqus.lazyLoadClass || '')) + .css('cursor', 'pointer') + .bind('click', function (event) { + $(event.currentTarget).remove(); + Drupal.disqus.loadCommentScript(disqus_shortname); + }); + break; + + case 'scroll': + $(window).scroll(function scrollHandler(event) { + if ($(window).scrollTop() + $(window).height() > $('#disqus_thread').offset().top) { + Drupal.disqus.loadCommentScript(disqus_shortname); + $(window).unbind('scroll', scrollHandler); + } + }); + break; + } + } + else { + Drupal.disqus.loadCommentScript(disqus_shortname); + } }); } @@ -83,14 +120,7 @@ Drupal.behaviors.disqus = { if (settings.disqusComments || false) { // Ensure that comment numbers JavaScript is only loaded once. $('body').once('disqusComments').each(function () { - disqus_shortname = settings.disqusComments; - // Make the AJAX call to get the number of comments. - jQuery.ajax({ - type: 'GET', - url: '//' + disqus_shortname + '.disqus.com/count.js', - dataType: 'script', - cache: false - }); + Drupal.disqus.loadCountScript(settings.disqusComments); }); } } diff --git a/src/DisqusCommentManager.php b/src/DisqusCommentManager.php index efb5443..a3b253b 100644 --- a/src/DisqusCommentManager.php +++ b/src/DisqusCommentManager.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityFieldManagerInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Component\Utility\SafeMarkup; use Drupal\Core\Url; /** @@ -14,6 +15,16 @@ use Drupal\Core\Url; class DisqusCommentManager implements DisqusCommentManagerInterface { /** + * Lazy load the Disqus script when the Disqus comment block becomes visible. + */ + const DISQUS_LAZY_LOAD_ON_SCROLL = 'scroll'; + + /** + * Lazy load the Disqus script when an element is clicked. + */ + const DISQUS_LAZY_LOAD_ON_CLICK = 'click'; + + /** * The current user. * * @var \Drupal\Core\Session\AccountInterface @@ -180,5 +191,26 @@ class DisqusCommentManager implements DisqusCommentManagerInterface { return $data; } + + /** + * Assembles data about lazy loading. + * + * @return array + */ + function lazy_load_settings() { + $data = array(); + + switch (\Drupal::config('disqus.settings')->get('advanced.lazy_loading.method')) { + case DisqusCommentManager::DISQUS_LAZY_LOAD_ON_SCROLL: + $data['lazyLoadMethod'] = 'scroll'; + break; + case DisqusCommentManager::DISQUS_LAZY_LOAD_ON_CLICK: + $data['lazyLoadClass'] = SafeMarkup::checkPlain(\Drupal::config('disqus.settings')->get('advanced.lazy_loading.class')); + $data['lazyLoadMethod'] = 'click'; + break; + } + + return $data; + } } diff --git a/src/Element/Disqus.php b/src/Element/Disqus.php index 4ad250e..99a47fc 100644 --- a/src/Element/Disqus.php +++ b/src/Element/Disqus.php @@ -62,7 +62,7 @@ class Disqus extends RenderElement { /** @var \Drupal\Core\Render\RendererInterface $renderer */ $renderer = \Drupal::service('renderer'); $element = [ - '#theme_wrappers' => ['disqus_noscript', 'container'], + '#theme_wrappers' => ['disqus_noscript', 'disqus_lazy_load', 'container'], '#attributes' => ['id' => 'disqus_thread'], ]; $renderer->addCacheableDependency($element, $disqus_settings); @@ -93,6 +93,11 @@ class Disqus extends RenderElement { if ($disqus_settings->get('advanced.sso.disqus_sso')) { $disqus += \Drupal::service('disqus.manager')->ssoSettings(); } + + // Lazy loading configuration. + if (\Drupal::config('disqus.settings')->get('advanced.lazy_loading.status')) { + $disqus += \Drupal::service('disqus.manager')->lazy_load_settings(); + } // Check if we want to track new comments in Google Analytics. if ($disqus_settings->get('behavior.disqus_track_newcomment_ga')) { diff --git a/src/Form/DisqusSettingsForm.php b/src/Form/DisqusSettingsForm.php index 07832d4..ea12c12 100644 --- a/src/Form/DisqusSettingsForm.php +++ b/src/Form/DisqusSettingsForm.php @@ -4,6 +4,7 @@ namespace Drupal\disqus\Form; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\ConfigFormBase; +use Drupal\disqus\DisqusCommentManager; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; @@ -266,6 +267,49 @@ class DisqusSettingsForm extends ConfigFormBase { ], ]; + $form['advanced']['lazy_loading'] = [ + '#weight' => 6, + '#type' => 'fieldset', + '#title' => t('Lazy Loading'), + '#collapsible' => FALSE, + '#collapsed' => FALSE, + ]; + + $form['advanced']['lazy_loading']['disqus_lazy_load'] = [ + '#type' => 'checkbox', + '#title' => t('Use Lazy Loading'), + '#description' => t('Prevent the Disqus script from loading until triggered by user activity.'), + '#default_value' => $disqus_config->get('advanced.lazy_loading.status'), + ]; + + $form['advanced']['lazy_loading']['disqus_lazy_load_method'] = [ + '#type' => 'select', + '#title' => t('Lazy Loading Trigger'), + '#description' => t('The type of user activity used to determine when the Disqus script is loaded.'), + '#default_value' => $disqus_config->get('advanced.lazy_loading.method'), + '#options' => [ + DisqusCommentManager::DISQUS_LAZY_LOAD_ON_SCROLL => t('When the Disqus block scrolls into view'), + DisqusCommentManager::DISQUS_LAZY_LOAD_ON_CLICK => t('When the user clicks on an HTML element'), + ], + '#states' => [ + 'visible' => [ + 'input[name="disqus_lazy_load"]' => ['checked' => TRUE], + ], + ], + ]; + + $form['advanced']['lazy_loading']['disqus_lazy_load_class'] = [ + '#type' => 'textfield', + '#title' => t('Triggering Class'), + '#description' => t('The HTML class of the elements that trigger the lazy loading.'), + '#default_value' => $disqus_config->get('advanced.lazy_loading.class'), + '#states' => [ + 'visible' => [ + 'select[name="disqus_lazy_load_method"]' => ['value' => DisqusCommentManager::DISQUS_LAZY_LOAD_ON_CLICK], + ], + ], + ]; + return parent::buildForm($form, $form_state); } @@ -285,6 +329,9 @@ class DisqusSettingsForm extends ConfigFormBase { ->set('advanced.disqus_secretkey', $form_state->getValue('disqus_secretkey')) ->set('advanced.sso.disqus_sso', $form_state->getValue('disqus_sso')) ->set('advanced.sso.disqus_use_site_logo', $form_state->getValue('disqus_use_site_logo')) + ->set('advanced.lazy_loading.status', $form_state->getValue('disqus_lazy_load')) + ->set('advanced.lazy_loading.method', $form_state->getValue('disqus_lazy_load_method')) + ->set('advanced.lazy_loading.class', $form_state->getValue('disqus_lazy_load_class')) ->save(); if ($form_state->hasValue('disqus_api_update')) { diff --git a/templates/disqus-lazy-load.html.twig b/templates/disqus-lazy-load.html.twig new file mode 100644 index 0000000..c844b30 --- /dev/null +++ b/templates/disqus-lazy-load.html.twig @@ -0,0 +1,10 @@ +{# +/** +* @file +* Display Suite reset template. +* +* Available variables: +* - disqus_message: The linked message to view the comments in Disqus site +*/ +#} +