slide_with_style.module in Select with Style 7
Defines a slider RANGE widget to create filters for numeric and list fields.
File
slide_with_style/slide_with_style.moduleView source
<?php
/**
* @file
* Defines a slider RANGE widget to create filters for numeric and list fields.
*/
/**
* Implements hook_help().
*/
function slide_with_style_help($path, $arg) {
switch ($path) {
case 'admin/help#slide_with_style':
$t = t('Configuration and usage instructions are in this <a href="@README">README</a> file.<br/>Known issues and solutions may be found on the <a href="@select_with_style">Select with Style</a> project page.', array(
'@README' => url(drupal_get_path('module', 'slide_with_style') . '/README.txt'),
'@select_with_style' => url('http://drupal.org/project/select_with_style'),
));
break;
}
return empty($t) ? '' : '<p>' . $t . '</p>';
}
/**
* Implements hook_menu().
*/
function slide_with_style_menu() {
$items = array();
// Put the administrative settings under System on the Configuration page.
$items['admin/config/system/slide_with_style'] = array(
'title' => 'Slide with Style',
'description' => 'Configure Slide with Style module.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'slide_with_style_admin_configure',
),
'access arguments' => array(
'administer site configuration',
),
'file' => 'slide_with_style.admin.inc',
);
return $items;
}
/**
* Implements hook_field_widget_info().
*/
function slide_with_style_field_widget_info() {
// @todo dynamically build list types, including contrib modules
$number_types = array(
'number_decimal',
'number_float',
'number_integer',
);
$list_types = array(
'list_text',
'list_integer',
'list_float',
);
$widget_info = array(
'slide_with_style_slider' => array(
'label' => t('Slider'),
'field types' => array_merge($number_types, $list_types),
'settings' => array(
'step' => 1,
'appearance' => array(
'with_textfield' => 'with_textfield',
'with_bubble' => 'with_bubble',
),
'css file' => '',
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_DEFAULT,
),
),
);
return $widget_info;
}
/**
* Implements hook_field_widget_form().
*
* Creates a textfield with CSS class for the JS to attach the slider to.
*/
function slide_with_style_field_widget_form(&$form, &$form_state, $field, $instance, $lang, $items, $delta, $element) {
switch ($field['module']) {
case 'list':
$additions = array(
'value' => array(
'#title' => $instance['label'],
'#type' => 'textfield',
'#default_value' => isset($items[$delta]) ? reset($items[$delta]) : NULL,
'#required' => !empty($element['#required']),
'#size' => 5,
),
);
break;
default:
// Use the default numeric field widget as a base.
$additions = number_field_widget_form($form, $form_state, $field, $instance, $lang, $items, $delta, $element);
// When used as a range, this field is read-only
$additions['value']['#size'] = min(8, $additions['value']['#size']);
}
// All additions are in $element['value']
$element += $additions;
// Define the class through which the javascript will find this textfield.
$element['value']['#attributes']['class'][] = "edit-slide-with-style-slider";
// Append to the textfield a placeholder for the slider
$element['value']['#suffix'] = '<div class="slide-with-style-slider"></div>';
if (empty($form_state['slider_id'])) {
$has_multiple_values = field_behaviors_widget('multiple values', $instance) == FIELD_BEHAVIOR_DEFAULT;
// id needs to match up with the element id generated by core for this input element.
$parent_id = '';
if (!empty($element['#field_parents'])) {
$parent_id .= trim($element['#field_parents'][0], '_ ') . '-';
if (!empty($element['#field_parents'][1])) {
$parent_id .= trim($element['#field_parents'][1], '_ ') . '-';
}
}
$base_id = 'edit-' . $parent_id . trim($instance['field_name'], '_ ') . "-{$lang}-";
$id = $base_id . ($has_multiple_values ? "{$delta}-value" : 'value');
}
else {
$id = $form_state['slider_id'];
}
// Pass jQueryUI slider parameters via the js settings.
$widget_settings = $instance['widget']['settings'];
$text_values = FALSE;
if ($field['module'] == 'number') {
$min = $instance['settings']['min'];
$max = $instance['settings']['max'];
}
elseif ($field['module'] == 'list') {
if (!empty($field['settings']['allowed_values'])) {
$text_values = $field['settings']['allowed_values'];
$keys = array_keys($text_values);
$min = reset($keys);
$max = array_pop($keys);
}
}
// Do not use $element['value']['#default_value'] -- it is the same as $items,
// but may be formatted.
if (isset($items[$delta]['value'])) {
$initial_value = $items[$delta]['value'];
}
elseif (isset($instance['default_value'][0])) {
$initial_value = $instance['default_value'][0]['value'];
}
else {
$initial_value = $min;
}
$slider_parameters = array(
drupal_html_class($id) => array(
'step' => empty($widget_settings['step']) ? 1 : $widget_settings['step'],
'min' => $min,
'max' => $max,
'value' => $initial_value,
'values' => empty($element['#default_values']) ? NULL : $element['#default_values'],
'textfield' => !empty($widget_settings['appearance']['with_textfield']),
'textvalues' => $text_values,
'bubble' => !empty($widget_settings['appearance']['with_bubble']),
'orientation' => empty($widget_settings['appearance']['vertical']) ? 'horizontal' : 'vertical',
'range' => empty($element['#default_values']) ? 'min' : TRUE,
'autosubmit' => !empty($element['#autosubmit']),
),
);
// Start by attaching settings or it will break global_filter_field_slider_widget_form_alter()
$element['value']['#attached']['js'][] = array(
'data' => array(
'slider' => $slider_parameters,
),
'type' => 'setting',
'scope' => 'header',
);
$path = drupal_get_path('module', 'slide_with_style');
$element['value']['#attached']['js'][] = $path . '/slide_with_style.js';
$element['value']['#attached']['css'][] = $path . '/slide_with_style.css';
$css_files = slide_with_style_css_files();
if (!empty($css_files[$widget_settings['css file']])) {
$element['value']['#attached']['css'][] = $css_files[$widget_settings['css file']];
}
$element['value']['#attached']['library'][] = array(
'system',
'ui.slider',
);
// Just in case we need to do more stuff after the form has been built...
$element['value']['#process'][] = 'slide_with_style_field_widget_process';
return $element;
}
/**
* Element #process callback retains slider value in case of validation errors.
*
* Without this a validation error elsewhere on the form will result in the
* slider falling back to the value it had when the form was first loaded.
*/
function slide_with_style_field_widget_process($element, &$form_state, $form) {
$parents = $element['#parents'];
foreach ($element['#attached']['js'][0]['data']['slider'] as &$slider_parameters) {
// Loops only once. PS: Surely there's a more elegant way...
if (!empty($form_state['values'][$parents[0]]) && is_array($form_state['values'][$parents[0]]) && !empty($form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]])) {
$slider_parameters['value'] = $form_state['values'][$parents[0]][$parents[1]][$parents[2]][$parents[3]];
}
}
return $element;
}
/**
* Implements hook_field_widget_settings_form().
*/
function slide_with_style_field_widget_settings_form($field, $instance) {
$settings = $instance['widget']['settings'];
switch ($instance['widget']['type']) {
case 'slide_with_style_slider':
$form['appearance'] = array(
'#type' => 'checkboxes',
'#title' => t('Slider appearance'),
'#default_value' => $settings['appearance'],
'#options' => array(
'with_textfield' => t('with synchronised text field'),
'with_bubble' => t('with value bubble'),
'vertical' => t('vertical instead of horizontal'),
),
);
if ($field['module'] == 'number') {
$form['step'] = array(
'#type' => 'textfield',
'#title' => t('Step'),
'#default_value' => $settings['step'],
'#description' => t('The increment that the slider should snap to.'),
'#element_validate' => array(
'_element_validate_number',
),
'#required' => TRUE,
);
}
$options = array(
'' => 'core (no styling)',
);
foreach (slide_with_style_css_files() as $name => $filespec) {
$options[$name] = $name;
}
$form['css file'] = array(
'#type' => 'select',
'#multiple' => FALSE,
'#size' => 1,
'#title' => t('Additional slider styling file'),
'#default_value' => $settings['css file'],
'#options' => $options,
'#description' => t('The directory where the above files are looked up may be changed on the Slide with Style <a href="@href">configuraton page</a>.', array(
'@href' => url('admin/config/system/slide_with_style'),
)),
);
break;
}
return $form;
}
/**
* Implements hook_field_widget_error().
*
* @see number_field_widget_validate()
* @see form_error()
*/
function slide_with_style_field_widget_error($element, $error, $form, &$form_state) {
form_error($element, $error['message']);
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Make min/max required when using any of the slider widgets.
*/
function slide_with_style_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
if ($form['#instance']['widget']['type'] == 'slide_with_style_slider') {
$form['instance']['settings']['min']['#required'] = TRUE;
$form['instance']['settings']['max']['#required'] = TRUE;
}
}
/**
* Returns an array of CSS files in a directory.
*
* @param $dir
* A stream wrapper URI that is a directory or NULL to use the directory
* set on the configuration page.
*
* @return
* An array of full CSS file names in the supplied directory.
*/
function slide_with_style_css_files($dir = NULL) {
if (empty($dir)) {
$default_path = drupal_get_path('module', 'slide_with_style') . '/css';
$path = variable_get('slide_with_style_css_directory', $default_path);
$dirname = DRUPAL_ROOT . "/{$path}";
}
else {
// not tested, not used
$dirname = file_stream_wrapper_uri_normalize($dir);
}
$files = array();
if ($all_files = @scandir($dirname)) {
foreach ($all_files as $filename) {
if (drupal_substr($filename, -4) == '.css' && is_file("{$dirname}/{$filename}")) {
$files[$filename] = "{$path}/{$filename}";
}
}
}
return $files;
}
/**
* Return a list of all instances belonging to the supplied field.
*
* @param string $field_name
* Name of the field whose instances are to be returned.
* @return array
* Array of instances belonging to the specified field.
*/
function slide_with_style_get_field_instances($field_name) {
$instances = array();
foreach (field_info_instances() as $type_bundles) {
foreach ($type_bundles as $bundle_instances) {
foreach ($bundle_instances as $fld_name => $instance) {
if ($fld_name == $field_name) {
$instances[] = $instance;
}
}
}
}
return $instances;
}
/**
* Implements hook_views_api().
*/
function slide_with_style_views_api() {
return array(
'api' => views_api_version(),
'path' => drupal_get_path('module', 'slide_with_style') . '/views',
);
}
Functions
Name | Description |
---|---|
slide_with_style_css_files | Returns an array of CSS files in a directory. |
slide_with_style_field_widget_error | Implements hook_field_widget_error(). |
slide_with_style_field_widget_form | Implements hook_field_widget_form(). |
slide_with_style_field_widget_info | Implements hook_field_widget_info(). |
slide_with_style_field_widget_process | Element #process callback retains slider value in case of validation errors. |
slide_with_style_field_widget_settings_form | Implements hook_field_widget_settings_form(). |
slide_with_style_form_field_ui_field_edit_form_alter | Implements hook_form_FORM_ID_alter(). |
slide_with_style_get_field_instances | Return a list of all instances belonging to the supplied field. |
slide_with_style_help | Implements hook_help(). |
slide_with_style_menu | Implements hook_menu(). |
slide_with_style_views_api | Implements hook_views_api(). |