You are here

image_lazy_loader.module in Image Lazy Loader 8

Same filename and directory in other branches
  1. 7 image_lazy_loader.module

Add Lozad lazy-loading to image / responsive image fields.

File

image_lazy_loader.module
View source
<?php

/**
 * @file
 * Add Lozad lazy-loading to image / responsive image fields.
 */
use Drupal\Core\Field\FormatterInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Implements hook_help().
 *
 * @inheritdoc
 */
function image_lazy_loader_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.image_lazy_loader':
      $text = file_get_contents(dirname(__FILE__) . '/README.md');
      if (!\Drupal::moduleHandler()
        ->moduleExists('markdown')) {
        return '<pre>' . $text . '</pre>';
      }
      else {

        // Use the Markdown filter to render the README.
        $filter_manager = \Drupal::service('plugin.manager.filter');
        $settings = \Drupal::configFactory()
          ->get('markdown.settings')
          ->getRawData();
        $config = [
          'settings' => $settings,
        ];
        $filter = $filter_manager
          ->createInstance('markdown', $config);
        return $filter
          ->process($text, 'en');
      }
  }
  return NULL;
}

/**
 * Implements hook_field_formatter_third_party_settings_form().
 *
 * {@inheritdoc}
 */
function image_lazy_loader_field_formatter_third_party_settings_form(FormatterInterface $plugin, FieldDefinitionInterface $field_definition, $view_mode, $form, FormStateInterface $form_state) {
  $element = [];

  // Add a checkbox to settings array to determine if image will be lazyloaded.
  if ($plugin
    ->getPluginId() == 'responsive_image' || $plugin
    ->getPluginId() == 'image') {
    $element['lazy_load_responsive_image'] = [
      '#type' => 'checkbox',
      '#title' => t('Lazy load this image'),
      '#default_value' => $plugin
        ->getThirdPartySetting('image_lazy_loader', 'lazy_load_responsive_image'),
    ];
  }
  return $element;
}

/**
 * Implements hook_preprocess_HOOK().
 */
function image_lazy_loader_preprocess_field(&$variables) {

  // Provide an extra variable to the field to establish if we should lazy-load
  // this image or not.
  $formatters = [
    'responsive_image',
    'image',
  ];
  if (in_array($variables['element']['#formatter'], $formatters)) {
    $entity = $variables['element']['#object'];
    $view_mode = $variables['element']['#view_mode'];
    $field_name = $variables['element']['#field_name'];

    // Get the field formatter settings.
    $entity_display = EntityViewDisplay::collectRenderDisplay($entity, $view_mode);
    $field_display = $entity_display
      ->getComponent($field_name);

    // Make the setting available in the field template.
    if (isset($field_display['third_party_settings'], $field_display['third_party_settings']['image_lazy_loader']) && ($is_lazy_loaded = $field_display['third_party_settings']['image_lazy_loader']['lazy_load_responsive_image'])) {
      $variables['#attached']['library'][] = 'image_lazy_loader/lozad';
      foreach ($variables['items'] as &$item) {
        $item['content']['#item_attributes']['lazy'] = TRUE;
        $item['#attributes']['lazy_load_responsive_image'] = $is_lazy_loaded;
      }
    }
  }
}

/**
 * Implements hook_preprocess_responsive_image().
 *
 * Prepare the variables to pass attributes to the template so that the
 * Lozad plugin will pick up the image.
 */
function image_lazy_loader_preprocess_responsive_image(&$variables) {
  $sources = $variables['sources'];
  $is_lazy_loaded = FALSE;
  if (isset($variables['attributes'], $variables['attributes']['lazy'])) {
    $is_lazy_loaded = $variables['attributes']['lazy'];
  }
  $variables['is_lazy'] = $is_lazy_loaded;
  if ($is_lazy_loaded && isset($sources)) {
    $variables['attributes']['class'][] = 'lozad';
    if (isset($variables['img_element'], $variables['img_element']['#uri'])) {
      $variables['attributes']['data-iesrc'] = $variables['img_element']['#uri'];
    }
    else {
      if (isset($sources[0], $sources[0]['srcset'])) {
        $variables['attributes']['data-iesrc'] = $sources[0]['srcset'];
      }
    }
    foreach ($sources as &$source) {
      if (isset($source['srcset'])) {
        $source['class'] = 'lozad';
      }
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Swap the 'srcset' attribute for the 'data-srcset' that Lozad expets.
 * Add a class to the image tag, too.
 */
function image_lazy_loader_preprocess_image(&$variables) {
  $is_lazy_loaded = FALSE;
  if (isset($variables['attributes'], $variables['attributes']['lazy'])) {
    $is_lazy_loaded = $variables['attributes']['lazy'];
  }
  if ($is_lazy_loaded) {
    if (isset($variables['attributes']['srcset'])) {
      $variables['attributes']['data-srcset'] = $variables['attributes']['srcset'];
      unset($variables['attributes']['srcset']);
    }
    else {
      $variables['attributes']['data-src'] = $variables['attributes']['src'];
    }
    $variables['attributes']['src'] = '';
    $variables['attributes']['class'][] = 'lozad';
    $variables['lazy'] = TRUE;
  }
  unset($variables['attributes']['lazy']);
}

/**
 * Implements hook_theme_registry_alter().
 *
 * Swap out for an updated template.
 */
function image_lazy_loader_theme_registry_alter(&$theme_registry) {
  $theme_registry['responsive_image']['path'] = drupal_get_path('module', 'image_lazy_loader') . '/templates';
}