You are here

slick_slideshow.module in Slick Slideshow Lite 7

Defines a system for adding the Slick responsive slideshow library to Drupal.

File

slick_slideshow.module
View source
<?php

/**
 * @file
 * Defines a system for adding the Slick responsive slideshow library to Drupal.
 */
define('SLICK_SLIDESHOW_LINK', variable_get('slick_slideshow_link', FALSE));
define('SLICK_SLIDESHOW_PATH', drupal_get_path('module', 'slick_slideshow'));

/**
 * Implements hook_libraries_info().
 */
function slick_slideshow_libraries_info() {
  $libraries = array();
  $libraries['slick'] = array(
    'name' => 'Slick Slideshow',
    'vendor url' => 'http://kenwheeler.github.io/slick/',
    'download url' => SLICK_SLIDESHOW_LINK,
    'version arguments' => array(
      'file' => 'slick/slick.js',
      'pattern' => '/Slick v(\\d+\\.+\\d+)/',
      'lines' => 2,
    ),
    'files' => array(
      'js' => array(
        'slick/slick.js',
      ),
    ),
  );
  return $libraries;
}

/**
 * Implements hook_library().
 */
function slick_slideshow_library() {
  $library_path = libraries_get_path('slick');
  $libraries['slick'] = array(
    'title' => 'Slick Slideshow',
    'website' => 'http://kenwheeler.github.io/slick/',
    'version' => '1.x',
    'js' => array(
      $library_path . '/slick/slick.js' => array(
        'scope' => 'footer',
      ),
    ),
    'css' => array(
      $library_path . '/slick/slick.css' => array(
        'type' => 'file',
        'media' => 'screen',
      ),
      $library_path . '/slick/slick-theme.css' => array(
        'type' => 'file',
        'media' => 'screen',
      ),
    ),
  );
  return $libraries;
}

/**
 * Implements hook_field_formatter_info().
 */
function slick_slideshow_field_formatter_info() {
  $settings = _slick_slideshow_settings_generate();
  foreach ($settings as &$setting) {
    $setting = '';
  }
  return array(
    'slick_slideshow' => array(
      'label' => t('Slick Slideshow'),
      'description' => t('Displays the field as a Slick slideshow. The field must allow for more than 1 value entered. Works best with unlimited allowed values.'),
      'field types' => array(
        'image',
      ),
      'settings' => $settings,
    ),
  );
}

/**
 * Implements hook_field_formatter_settings_form().
 */
function slick_slideshow_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];

  // Will add more settings in the future.
  $element = _slick_slideshow_settings_generate($settings);
  return $element;
}

/**
 * Implements hook_field_formatter_settings_summary().
 */
function slick_slideshow_field_formatter_settings_summary($field, $instance, $view_mode) {
  $display = $instance['display'][$view_mode];
  $settings = $display['settings'];
  $summary = array();
  if (function_exists('image_style_options')) {
    $image_styles = image_style_options(FALSE, PASS_THROUGH);

    // Unset possible 'No defined styles' option.
    unset($image_styles['']);
  }

  // Styles could be lost because of enabled/disabled modules that define
  // their styles in code.
  $summary[] = t('Field Settings:');
  if (isset($image_styles) && isset($settings['slickField']['image_style']) && isset($image_styles[$settings['slickField']['image_style']])) {
    $summary[] = t('Image style: @style', array(
      '@style' => $image_styles[$settings['slickField']['image_style']],
    ));
  }
  else {
    $summary[] = t('Original image');
  }
  if (isset($settings['slickField']['captions']) && $settings['slickField']['captions']) {
    $summary[] = t('Image captions enabled');
  }
  $summary[] = "\n";
  $summary[] = t('Slick Slideshow Settings:');
  if (isset($settings['slickSettings']['slidesToShow']) && $settings['slickSettings']['slidesToShow']) {
    $summary[] = t('Slides displayed: @show', array(
      '@show' => $settings['slickSettings']['slidesToShow'],
    ));
  }
  else {
    $summary[] = t('Slides displayed: 1');
  }
  if (isset($settings['slickSettings']['slidesToScroll']) && $settings['slickSettings']['slidesToScroll']) {
    $summary[] = t('Slides scrolled on change: @scroll', array(
      '@scroll' => $settings['slickSettings']['slidesToScroll'],
    ));
  }
  else {
    $summary[] = t('Slides scrolled on change: 1');
  }
  if (isset($settings['slickSettings']['infinite']) && $settings['slickSettings']['infinite']) {
    $summary[] = t('Infinite scroll enabled');
  }
  if (isset($settings['slickSettings']['fade']) && $settings['slickSettings']['fade']) {
    $summary[] = t('Fade enabled');
  }
  if (isset($settings['slickSettings']['dots']) && $settings['slickSettings']['dots']) {
    $summary[] = t('Dots enabled');
  }
  if (isset($settings['slickSettings']['autoplay']) && $settings['slickSettings']['autoplay']) {
    $summary[] = t('Auto play enabled');
  }
  if (isset($settings['slickSettings']['autoplaySpeed']) && $settings['slickSettings']['autoplaySpeed']) {
    $summary[] = t('Auto play change interval: @autoplay_speed', array(
      '@autoplay_speed' => $settings['slickSettings']['autoplaySpeed'] . ' ms',
    ));
  }
  if (isset($settings['slickSettings']['pauseOnHover']) && $settings['slickSettings']['pauseOnHover']) {
    $summary[] = t('Pause on hover enabled');
  }
  return implode('<br />', $summary);
}

/**
 * Implements hook_field_formatter_view().
 */
function slick_slideshow_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  $element = array();

  // For now, just add Slick to image fields.
  switch ($field['type']) {
    case 'image':
      if ($display['type'] == 'slick_slideshow') {
        foreach ($items as $delta => $item) {
          $element[$delta] = array(
            '#theme' => 'slick_slideshow_image_slide',
            '#item' => $item,
            '#image_style' => isset($display['settings']['slickField']['image_style']) ? $display['settings']['slickField']['image_style'] : '',
            '#captions' => isset($display['settings']['slickField']['captions']) ? $display['settings']['slickField']['captions'] : '',
          );
        }
      }

      // Set image field's default settings
      if (isset($display['settings']['slickSettings']) && empty($display['settings']['slickSettings'])) {
        $display['settings']['slickSettings'] = array(
          'slidesToShow' => 1,
          'slidesToScroll' => 1,
        );
      }

      // Get image field's Slick slideshow settings.
      $settings = _slick_slideshow_settings_alter($display['settings']['slickSettings']);

      // Create Slick slideshow.
      $field_selector = '#slick-slideshow-' . str_replace('_', '-', $field['field_name']);
      $target = '.field-items';
      slick_slideshow_create($field_selector, $settings, $target);
      break;
  }
  return $element;
}

/**
 * Implements hook_preprocess_field().
 */
function slick_slideshow_preprocess_field(&$vars) {
  $element = isset($vars['element']) ? $vars['element'] : '';
  if (!empty($element) && isset($element['#formatter']) && $element['#formatter'] == 'slick_slideshow') {

    // Add a custom theme suggestion to the field.
    // ex: field--image--slick-slideshow.tpl.php
    $vars['theme_hook_suggestions'][] = 'field__' . $element['#field_type'] . '__slick_slideshow';

    // Add a custom slick-slideshow id to the field.
    $vars['attributes_array'] = array(
      'id' => array(
        'slick-slideshow-' . str_replace('_', '-', $element['#field_name']),
      ),
    );
  }
}

/**
 * Implements hook_theme().
 */
function slick_slideshow_theme() {
  return array(
    // Individual slide theme.
    'slick_slideshow_image_slide' => array(
      'variables' => array(
        'item' => array(),
        'image_style' => array(),
        'captions' => array(),
      ),
      'template' => 'templates/slick-slideshow--image--slide',
      'path' => SLICK_SLIDESHOW_PATH,
    ),
    // Custom image field theme.
    'field__image__slick_slideshow' => array(
      'template' => 'templates/field--image--slick-slideshow',
      'base hook' => 'field',
      'path' => SLICK_SLIDESHOW_PATH,
    ),
  );
}

/*
 * This function loads the required JavaScripts and settings for a Slick
 * slideshow instance.
 *
 * @param string $field_selector
 *  Field element selector for the Slick slideshow to fire on.
 * @param array $settings
 *  Settings array with keys that match the Slick JS setting variables.
 * @param string $target (optional)
 *  If the $field_selector isn't the element that Slick should be created on,
 *  specify the $target as a child element of the $field_selector.
 */
function slick_slideshow_create($field_selector, $settings, $target = NULL) {

  // Make sure $field_id is populated.
  if (empty($field_selector)) {
    watchdog('slick_slideshow', 'No field selector provided to slick_slideshow_create.', WATCHDOG_WARNING);
    return;
  }

  // Make sure $settings is an array.
  if (empty($settings) || !is_array($settings)) {
    watchdog('slick_slideshow', 'No settings provided to slick_slideshow_create or settings is not an array.', WATCHDOG_WARNING);
    return;
  }

  // Build JS settings array.
  $slick_settings[$field_selector] = array(
    'settings' => $settings,
    'target' => $target,
  );

  // Load and create Slick slideshow.
  drupal_add_library('slick_slideshow', 'slick', FALSE);
  drupal_add_js(array(
    'slickSlideshowSettings' => $slick_settings,
  ), 'setting');
  drupal_add_js(SLICK_SLIDESHOW_PATH . '/js/slick_slideshow.function.js', array(
    'scope' => 'footer',
    'weight' => 9,
  ));
  drupal_add_js(SLICK_SLIDESHOW_PATH . '/js/slick_slideshow.load.js', array(
    'scope' => 'footer',
    'weight' => 10,
  ));
}

/*
 * This function updates specified options in a Slick slideshow instance.
 *
 * @param string $field_selector
 *  Field element selector that the Slick slideshow belongs to.
 * @param array $settings
 *  Settings array with options to update.
 * @param string $target (optional)
 *  If the $field_selector isn't the element that Slick should be created on,
 *  specify the $target as a child element of the $field_selector.
 */
function slick_slideshow_update($field_selector, $settings, $target = NULL) {

  // Build JS settings array.
  $slick_settings[$field_selector] = array(
    'settings' => $settings,
    'target' => $target,
  );

  // Update Slick slideshow.
  drupal_add_js(array(
    'slickSlideshowSettingsUpdate' => $slick_settings,
  ), 'setting');
  drupal_add_js(SLICK_SLIDESHOW_PATH . '/js/slick_slideshow.update.js', array(
    'scope' => 'footer',
    'weight' => 11,
  ));
}

/**
 * Generate settings array.
 *
 * @param array $settings (optional)
 *  Pass existing settings into the array.
 */
function _slick_slideshow_settings_generate($settings = array()) {
  $image_styles = function_exists('image_style_options') ? image_style_options(FALSE, PASS_THROUGH) : array();
  $form_settings = array(
    'slickField' => array(
      '#title' => t('Field Settings'),
      '#type' => 'fieldset',
      'image_style' => array(
        '#title' => t('Image style'),
        '#type' => 'select',
        '#empty_option' => t('None (original image)'),
        '#options' => $image_styles,
      ),
      'captions' => array(
        '#title' => t('Enable captions'),
        '#description' => t('If enabled, a caption will appear on the slides based on the image\'s title field.'),
        '#type' => 'checkbox',
      ),
    ),
    'slickSettings' => array(
      '#title' => t('Slick Slideshow Settings'),
      '#type' => 'fieldset',
      'slidesToShow' => array(
        '#title' => t('Slides displayed'),
        '#type' => 'textfield',
        '#element_validate' => array(
          'element_validate_integer_positive',
        ),
        '#required' => TRUE,
      ),
      'slidesToScroll' => array(
        '#title' => t('Slides scrolled on change'),
        '#type' => 'textfield',
        '#element_validate' => array(
          'element_validate_integer_positive',
        ),
        '#required' => TRUE,
      ),
      'infinite' => array(
        '#title' => t('Enable infinite scrolling'),
        '#type' => 'checkbox',
      ),
      'dots' => array(
        '#title' => t('Enable dots navigation'),
        '#type' => 'checkbox',
      ),
      'fade' => array(
        '#title' => t('Enable fade transition'),
        '#type' => 'checkbox',
      ),
      'autoplay' => array(
        '#title' => t('Enable autoplay'),
        '#type' => 'checkbox',
      ),
      'autoplaySpeed' => array(
        '#title' => t('Auto play change interval'),
        '#description' => t('Enter interal value in ms. Default is 3000 (3 seconds).'),
        '#type' => 'textfield',
        '#element_validate' => array(
          'element_validate_integer_positive',
        ),
      ),
      'pauseOnHover' => array(
        '#title' => t('Enable pause on hover'),
        '#type' => 'checkbox',
      ),
    ),
  );
  if (!empty($settings)) {
    foreach ($form_settings as $fkey => $fieldset) {
      foreach ($fieldset as $skey => $setting) {
        if (is_array($form_settings[$fkey][$skey])) {
          $form_settings[$fkey][$skey]['#default_value'] = isset($settings[$fkey][$skey]) ? $settings[$fkey][$skey] : null;
        }
      }
    }
  }

  // Set numeric default values if null
  $numeric_settings = array(
    'slidesToShow',
    'slidesToScroll',
  );
  foreach ($numeric_settings as $num_setting) {
    if (empty($form_settings['slickSettings'][$num_setting]['#default_value'])) {
      $form_settings['slickSettings'][$num_setting]['#default_value'] = 1;
    }
  }
  return $form_settings;
}

/**
 * Alter settings values to be in the correct format for Slick.
 *
 * @param array $settings
 *  The settings array to alter and pass to Slick.
 */
function _slick_slideshow_settings_alter($settings) {
  if (!empty($settings)) {

    // Unset all of the autoplay settings if autoplay isn't checked.
    if (!isset($settings['autoplay']) || !$settings['autoplay']) {
      unset($settings['autoplaySpeed']);
      unset($settings['pauseOnHover']);
    }
    foreach ($settings as &$setting) {

      // Slick doesn't understand 0 = FALSE.
      if ($setting === 0) {
        $setting = FALSE;
      }

      // Slick doesn't understand 1 = TRUE.
      if ($setting === 1) {
        $setting = TRUE;
      }

      // Change strings to int.
      if (is_numeric($setting) && is_string($setting)) {
        $setting = (int) $setting;
      }
    }
    return $settings;
  }
}