Rewrite the image markup from specific image field In a Drupal 7 site, I have an image field that allows unlimited images, called field_gallery_images. I built a template file for this field to create a custom image slider. I want to rewrite the HTML markup for the image to add a lazy-load component. So, instead of:

&lt;img src="/sites/default/files/myimage.jpg" width="668" height="500"&gt;


I want: 

&lt;img data-lazy="/sites/default/files/myimage.jpg" width="668" height="500" class="lazyload"&gt;


Right now, the images are being run through theme_image() and so by the time it gets to the template, the markup is all set. I only want to alter the markup for this one field. I tried theme_preprocess_image(), but that altered all images.
I assume that you are using Drupal 7.

Short Answer

Implements template_preprocess_field() and overrides theme_image().

/**
 * Implements template_preprocess_field().
 */
function mytheme_preprocess_field(&amp;$variables) {
  $element = &amp;$variables['element'];

  if ($element['#field_name'] === 'field_image') {
    foreach (element_children($element) as $key) {
      $item = &amp;$element[$key]['#item'];

      $src = file_create_url($item['uri']);
      unset($item['uri']);
      $item['attributes']['data-lazy'] = $src;
      $item['attributes']['class'] = array('lazyload');

      $element['#items'][$key] = $item;
      $variables['items'][$key]['#item'] = $item;
    }
  }
}

/**
 * Overrides theme_image().
 */
function mytheme_image($variables) {
  $attributes = $variables['attributes'];

  if (!empty($variables['path']) || !isset($attributes['data-lazy')) {
    $attributes['src'] = file_create_url($variables['path']);
  }

  foreach (array('width', 'height', 'alt', 'title') as $key) {

    if (isset($variables[$key])) {
      $attributes[$key] = $variables[$key];
    }
  }

  return '&lt;img' . drupal_attributes($attributes) . ' /&gt;';
}




Long Answer

By implementing template_preprocess_field(), you can alter the theme variables and also the theme function for a field.

Example code:

/**
 * Implements template_preprocess_field().
 */
function mytheme_preprocess_field(&amp;$variables) {
  $element = &amp;$variables['element'];

  if ($element['#field_name'] === 'field_image') {
    foreach (element_children($element) as $key) {
      $item = &amp;$element[$key]['#item'];

      $src = file_create_url($item['uri']);
      unset($item['uri']);
      $item['attributes']['data-lazy'] = $src;
      $item['attributes']['class'] = array('lazyload');

      $element['#items'][$key] = $item;
      $variables['items'][$key]['#item'] = $item;
    }
  }
}


Remember to change field_image to the field name you defined.

It is the structure of $variables:



$variables['items'][0]['#item'] is a typical usage of theme function in render array. The code above has done a couple of things:


unset uri, which is used to format the attribute src in theme_image()
construct image path and assign it to the attribute data-lazy
add lazyload to class
synchronise the item array to different location of $variable


The last point is a bit weird, but there are 3 different location always store the same item array. They are


$variables['element'][0]['#item']
$variables['element']['#items'][0]
$variables['items'][0]['#item']


Theoretically, $variables['items'][0]['#item'] is the only one be used in theme function, But, in my opinion, it is better to change them at the same time for preventing any potential issue in future. (Maybe someone can provide more suggestion here?)

The last but not the least, you have to override the theme_image(). It is a global change but won't affect too much.

/**
 * Overrides theme_image().
 */
function mytheme_image($variables) {
  $attributes = $variables['attributes'];

  if (!empty($variables['path']) || !isset($attributes['data-lazy')) {
    $attributes['src'] = file_create_url($variables['path']);
  }

  foreach (array('width', 'height', 'alt', 'title') as $key) {

    if (isset($variables[$key])) {
      $attributes[$key] = $variables[$key];
    }
  }

  return '&lt;img' . drupal_attributes($attributes) . ' /&gt;';
}