You are here

select2widget.module in Select2 Field Widget 7

Same filename and directory in other branches
  1. 7.2 select2widget.module

Select2Widget module functionality.

File

select2widget.module
View source
<?php

/**
 * @file
 * Select2Widget module functionality.
 */

/**
 * Implements hook_help().
 */
function select2widget_help($path, $arg) {
  $output = '';
  switch ($path) {
    case 'admin/help#select2widget':
      $output = '<p>' . t('Provides a CCK widget for editing fields that allows users to use Select2 jquery plugin.') . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_field_widget_info().
 */
function select2widget_field_widget_info() {
  return array(
    'select2widget' => array(
      'label' => t('Select2Widget'),
      'field types' => array(
        'list',
        'list_text',
        'list_number',
        'node_reference',
        'taxonomy_term_reference',
        'user_reference',
      ),
      'behaviors' => array(
        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
        'default value' => FIELD_BEHAVIOR_CUSTOM,
      ),
    ),
  );
}

/**
 * Implements hook_field_widget_form().
 */
function select2widget_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {

  // Abstract over the actual field columns, to allow different field types to
  // reuse those widgets.
  $value_key = key($field['columns']);
  $type = str_replace('options_', '', $instance['widget']['type']);
  $multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
  $required = $element['#required'];
  $has_value = isset($items[0][$value_key]);
  $properties = _select2widget_options_properties($type, $multiple, $required, $has_value);
  $entity_type = $element['#entity_type'];
  $entity = $element['#entity'];

  // Prepare the list of options.
  $options = _select2widget_options_get_options($field, $instance, $properties, $entity_type, $entity);

  // Put current field values in shape.
  $default_value = _options_storage_to_form($items, $options, $value_key, $properties);
  switch ($type) {
    case 'select2widget':
      $element += array(
        '#type' => 'select',
        '#default_value' => $default_value,
        // Do not display a 'multiple' select box if there is only one option.
        '#multiple' => $multiple && count($options) > 1,
        '#options' => $options,
        '#process' => array(
          'select2widget_process_callback',
          'ajax_process_form',
        ),
      );
      break;
  }
  $element += array(
    '#value_key' => $value_key,
    '#element_validate' => array(
      'select2widget_field_widget_validate',
    ),
    '#properties' => $properties,
  );
  return $element;
}

/**
 * Process callback: 'select2widget' element type.
 */
function select2widget_process_callback($element, &$form_state, $form) {

  // Send Drupal.settings a reference to this form element.
  $data['select2widget']['elements'][$element['#id']] = array(
    'id' => $element['#id'],
  );

  // Attaching library, integration script, and settings array.
  $element['#attached']['library'][] = array(
    'select2widget',
    'select2',
  );
  $element['#attached']['js'][] = array(
    'type' => 'setting',
    'data' => $data,
  );
  return $element;
}

/**
 * Form element validation handler for options element.
 */
function select2widget_field_widget_validate($element, &$form_state) {
  if ($element['#required'] && $element['#value'] == '_none') {
    form_error($element, t('!name field is required.', array(
      '!name' => $element['#title'],
    )));
  }

  // Transpose selections from field => delta to delta => field, turning
  // multiple selected options into multiple parent elements.
  $items = _options_form_to_storage($element);
  form_set_value($element, $items, $form_state);
}

/**
 * Implements hook_field_widget_error().
 */
function select2widget_field_widget_error($element, $error, $form, &$form_state) {
  form_error($element, $error['message']);
}

/**
 * Describes the preparation steps required by each widget.
 */
function _select2widget_options_properties($type, $multiple, $required, $has_value) {
  $base = array(
    'filter_xss' => FALSE,
    'strip_tags' => FALSE,
    'empty_option' => FALSE,
    'optgroups' => FALSE,
  );
  $properties = array();
  switch ($type) {
    case 'select2widget':
      $properties = array(
        // Select boxes do not support any HTML tag.
        'strip_tags' => TRUE,
        'optgroups' => TRUE,
      );
      if ($multiple) {

        // Multiple select: add a 'none' option for non-required fields.
        if (!$required) {
          $properties['empty_option'] = 'option_none';
        }
      }
      else {

        // Single select: add a 'none' option for non-required fields,
        // and a 'select a value' option for required fields that do not come
        // with a value selected.
        if (!$required) {
          $properties['empty_option'] = 'option_none';
        }
        elseif (!$has_value) {
          $properties['empty_option'] = 'option_select';
        }
      }
      break;
  }
  return $properties + $base;
}

/**
 * Collects the options for a field.
 */
function _select2widget_options_get_options($field, $instance, $properties, $entity_type, $entity) {

  // Get the list of options.
  $options = (array) module_invoke($field['module'], 'options_list', $field, $instance, $entity_type, $entity);

  // Sanitize the options.
  _options_prepare_options($options, $properties);
  if (!$properties['optgroups']) {
    $options = options_array_flatten($options);
  }
  if ($properties['empty_option']) {
    $label = theme('select2widget_options_none', array(
      'instance' => $instance,
      'option' => $properties['empty_option'],
    ));
    $options = array(
      '_none' => $label,
    ) + $options;
  }
  return $options;
}

/**
 * Implements hook_theme().
 */
function select2widget_theme() {
  return array(
    'select2widget_options_none' => array(
      'variables' => array(
        'instance' => NULL,
        'option' => NULL,
      ),
    ),
  );
}

/**
 * Returns HTML for the label for the empty value that are not required.
 *
 * The default theme will display N/A for a radio list and '- None -'
 *for a select.
 *
 * @param array $variables
 *   An associative array containing:
 *   - instance: An array representing the widget requesting the options.
 *
 * @return string
 *   "None" string for select
 */
function theme_select2widget_options_none($variables) {
  $instance = $variables['instance'];
  $option = $variables['option'];
  $output = '';
  switch ($instance['widget']['type']) {
    case 'select2widget':
      $output = $option == 'option_none' ? t('- None -') : t('- Select a value -');
      break;
  }
  return $output;
}

/**
 * Implements hook_library().
 */
function select2widget_library() {
  module_load_include('module', 'libraries');
  $path = libraries_get_path('select2');
  $module_path = drupal_get_path("module", "select2widget");
  $libraries['select2'] = array(
    'title' => 'select2',
    'website' => 'http://ivaynberg.github.io/select2/',
    'version' => '3.4.1',
    'js' => array(
      $path . '/select2.js' => array(),
      $module_path . '/js/select2widget.js' => array(),
    ),
    'css' => array(
      $path . '/select2.css' => array(),
    ),
  );
  return $libraries;
}

/**
 * Implements hook_libraries_info().
 */
function select2widget_libraries_info() {
  return array(
    'select2' => array(
      'name' => 'select2',
      'vendor url' => 'http://ivaynberg.github.io/select2/',
      'download url' => 'https://github.com/ivaynberg/select2/archive/3.4.1.zip',
      'versions' => array(
        '3.4.1' => array(
          'variants' => array(
            'minified' => array(
              'files' => array(
                'js' => array(
                  'select2.min.js',
                ),
                'css' => array(
                  'select2.css',
                ),
              ),
            ),
            'source' => array(
              'files' => array(
                'js' => array(
                  'select2.js',
                ),
                'css' => array(
                  'select2.css',
                ),
              ),
            ),
          ),
          'integration files' => array(
            'select2widget' => array(
              'js' => array(
                'js/select2widget.js',
              ),
            ),
          ),
        ),
      ),
    ),
  );
}

Functions

Namesort descending Description
select2widget_field_widget_error Implements hook_field_widget_error().
select2widget_field_widget_form Implements hook_field_widget_form().
select2widget_field_widget_info Implements hook_field_widget_info().
select2widget_field_widget_validate Form element validation handler for options element.
select2widget_help Implements hook_help().
select2widget_libraries_info Implements hook_libraries_info().
select2widget_library Implements hook_library().
select2widget_process_callback Process callback: 'select2widget' element type.
select2widget_theme Implements hook_theme().
theme_select2widget_options_none Returns HTML for the label for the empty value that are not required.
_select2widget_options_get_options Collects the options for a field.
_select2widget_options_properties Describes the preparation steps required by each widget.