colorfield.module in Colorfield 7
A simple color field module with a color picker.
File
colorfield.moduleView source
<?php
/**
* @file
* A simple color field module with a color picker.
*/
/**
* Implements hook_theme().
*/
function colorfield_theme() {
return array(
'colorfield_colored_message' => array(
'variables' => array(
'text_color' => 'black',
'text_message' => '',
),
'template' => 'templates/colorfield-colored-message',
),
);
}
/**
* Implements hook_field_info().
*/
function colorfield_field_info() {
$info = array();
$info['colorfield'] = array(
'label' => t('Color'),
'description' => t('A field composed of an RGB color.'),
'default_widget' => 'colorfield_unified_textfield',
'default_formatter' => 'colorfield_color_swatch',
'instance_settings' => array(
'colorfield_options' => array(
'colorfield_enable_colorpicker' => TRUE,
'colorfield_colorpicker_type' => 'farbtastic',
),
),
);
if (module_exists('entity')) {
$info['colorfield']['property_type'] = 'text';
}
return $info;
}
/**
* Implements hook_element_info().
*/
function colorfield_element_info() {
$type['colorfield_picker'] = array(
'#input' => TRUE,
'#tree' => TRUE,
'#process' => array(
'colorfield_picker_element_process',
),
'#theme_wrappers' => array(
'form_element',
),
);
$type['colorfield_picker_minicolors'] = array(
'#input' => TRUE,
'#tree' => TRUE,
'#process' => array(
'colorfield_picker_minicolors_element_process',
),
'#theme_wrappers' => array(
'form_element',
),
);
$type['colorfield_rgb'] = array(
'#input' => TRUE,
'#tree' => TRUE,
'#process' => array(
'colorfield_rgb_element_process',
),
'#theme_wrappers' => array(
'form_element',
),
);
return $type;
}
/**
* Define the color picker with Javascript popup element processing.
* Add popup attributes to $element.
*/
function colorfield_picker_element_process($element, &$form_state, $form) {
$element['colorfield_picker'] = array(
'#type' => 'textfield',
'#size' => 7,
'#maxlength' => 7,
'#default_value' => isset($element['#default_value']['colorfield_picker']) ? $element['#default_value']['colorfield_picker'] : NULL,
'#attributes' => array(
'class' => array(
'colorfield-colorpicker',
),
),
'#attached' => array(
'library' => array(
array(
'system',
'farbtastic',
),
),
'js' => array(
drupal_get_path('module', 'colorfield') . '/js/colorfield-farbtastic.js',
),
),
'#suffix' => '<div class="colorfield-picker"></div>',
);
return $element;
}
/**
* Define the color picker with Javascript popup element processing.
* Add popup attributes to $element.
*/
function colorfield_picker_minicolors_element_process($element, &$form_state, $form) {
$element['colorfield_picker_minicolors'] = array(
'#type' => 'textfield',
'#size' => 7,
'#maxlength' => 7,
'#default_value' => isset($element['#default_value']['colorfield_picker_minicolors']) ? $element['#default_value']['colorfield_picker_minicolors'] : NULL,
'#attributes' => array(
'class' => array(
'colorfield-colorpicker',
),
),
);
if (($library = libraries_load('jquery-miniColors')) && !empty($library['loaded'])) {
$element['colorfield_picker_minicolors']['#attached'] = array(
'js' => array(
drupal_get_path('module', 'colorfield_minicolors') . '/js/colorfield-minicolors.js',
),
);
}
return $element;
}
/**
* Define the RGB field element.
*/
function colorfield_rgb_element_process($element, &$form_state, $form) {
$element['colorfield_rgb'] = array(
'#type' => 'fieldset',
'#title' => t('Select your color'),
'#description' => '<p>' . t('The 2-digit hexadecimal representation of the color saturation, like "44", "C2" or "FF".') . '</p>',
'#attributes' => array(
'class' => array(
'colorfield-split-field',
),
),
'#attached' => array(
'css' => array(
drupal_get_path('module', 'colorfield') . '/styles/colorfield.css',
),
),
'#suffix' => '<div class="clearfix"></div>',
);
if (isset($element['#default_value']['colorfield_rgb'])) {
$color = $element['#default_value']['colorfield_rgb'];
if (is_string($element['#default_value']['colorfield_rgb'])) {
if (strlen($color) == '7') {
$raw_value = substr($color, 1);
$color = array(
'r' => $raw_value[0] . $raw_value[1],
'g' => $raw_value[2] . $raw_value[3],
'b' => $raw_value[4] . $raw_value[5],
);
}
}
}
else {
$color = array(
'r' => '',
'g' => '',
'b' => '',
);
}
// Create a textfield for saturation values for Red, Green, and Blue.
foreach (array(
'r' => t('Red'),
'g' => t('Green'),
'b' => t('Blue'),
) as $key => $title) {
$element[$key] = array(
'#type' => 'textfield',
'#title' => $title,
'#size' => 2,
'#maxlength' => 2,
'#default_value' => $color[$key],
);
}
return $element;
}
/**
* Implements hook_field_validate().
*
* Validates that the inputed value matchs a hexadecimal color.
*
* @see colorfield_field_widget_error()
*/
function colorfield_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
// Remove potential empty fields.
$items = _field_filter_items($field, $items);
if ($instance['widget']['type'] == 'colorfield_unified_textfield') {
foreach ($items as $delta => $item) {
if (!empty($item['rgb'])) {
// Double check that we really have an hexadecimal value.
if (!preg_match('@^#[0-9a-f]{6}$@i', $item['rgb'])) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'colorfield_invalid',
'message' => t('Color must be a hexadecimal value (eg: #84CCAF).'),
);
}
}
}
}
elseif ($instance['widget']['type'] == 'colorfield_split_textfield') {
foreach ($items as $delta => $item) {
foreach ($item['rgb'] as $key => $color_component) {
// Check if every color component is a valid hexadecimal value.
if (!preg_match('@^[0-9a-f]{2}$@i', $color_component)) {
$errors[$field['field_name']][$langcode][$delta][] = array(
'error' => 'colorfield_invalid_component_value',
'message' => t('%name: the color component you specified is not valid, you must use a hexadecimal value (eg: 00, 5D, FF...).', array(
'%name' => $instance['label'],
)),
);
}
}
}
}
}
/**
* Implements hook_field_presave().
*/
function colorfield_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
// Rewrite the clean RGB value.
if ($instance['widget']['type'] == 'colorfield_split_textfield') {
foreach ($items as $key => $item) {
$items[$key]['rgb'] = '#' . implode('', $item['rgb']);
}
}
}
/**
* Implements hook_field_widget_error().
*/
function colorfield_field_widget_error($element, $error, $form, &$form_state) {
// Mark components in error.
form_error($element['rgb'], $error['message']);
}
/**
* Implements hook_field_is_empty().
*/
function colorfield_field_is_empty($item, $field) {
// Detect if the field is empty (the three color components are empty).
if (is_array($item['rgb'])) {
return empty($item['rgb']['r']) && empty($item['rgb']['g']) && empty($item['rgb']['b']);
}
else {
return empty($item['rgb']);
}
}
/**
* Implements hook_field_formatter_info().
*/
function colorfield_field_formatter_info() {
return array(
// This formatter displays the raw value of the color.
'colorfield_raw_rgb' => array(
'label' => t('Raw RGB value'),
'field types' => array(
'colorfield',
),
'settings' => array(
'display_hash' => TRUE,
),
),
// This formatter displays a DIV of the specified color.
'colorfield_color_swatch' => array(
'label' => t('Color swatch'),
'field types' => array(
'colorfield',
),
'settings' => array(
'width' => 20,
'height' => 20,
),
),
// This formatter displays a message colored with the inputed value.
'colorfield_colored_message' => array(
'label' => t('Colored message'),
'field types' => array(
'colorfield',
),
'settings' => array(
'message' => t('The color code in this field is @code'),
),
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function colorfield_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
// Expose the message to display as a setting.
if ($display['type'] == 'colorfield_colored_message') {
$element['message'] = array(
'#type' => 'textfield',
'#title' => t('Message to display'),
'#default_value' => $settings['message'],
'#description' => t('Note that you can use @code to display the value of the code in the message.'),
);
}
elseif ($display['type'] == 'colorfield_color_swatch') {
$element['width'] = array(
'#type' => 'textfield',
'#title' => t('Width of the block'),
'#size' => 3,
'#required' => TRUE,
'#element_validate' => array(
'element_validate_number',
),
'#default_value' => $settings['width'],
);
$element['height'] = array(
'#type' => 'textfield',
'#title' => t('Height of the block'),
'#size' => 3,
'#required' => TRUE,
'#element_validate' => array(
'element_validate_number',
),
'#default_value' => $settings['height'],
);
}
elseif ($display['type'] == 'colorfield_raw_rgb') {
$element['display_hash'] = array(
'#type' => 'checkbox',
'#title' => t('Display the # in the output of the color'),
'#default_value' => $settings['display_hash'],
);
}
return $element;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function colorfield_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$summary = array();
// Displays a dynamic message and replace @code by the value of the color
// code if it exists in the message.
if ($display['type'] == 'colorfield_colored_message') {
$summary[] = t('Message displayed: %message', array(
'%message' => $settings['message'],
));
if (strpos($settings['message'], '@code')) {
$summary[] = '<small>' . t('Note that @code will be replaced by the color picked.') . '</small>';
}
}
elseif ($display['type'] == 'colorfield_color_swatch') {
$summary[] = t('Width: @width px', array(
'@width' => $settings['width'],
));
$summary[] = t('Height: @height px', array(
'@height' => $settings['height'],
));
}
elseif ($display['type'] == 'colorfield_raw_rgb') {
$summary[] = $settings['display_hash'] ? t('The raw will be prefixed with #.') : t('The raw will not be prefixed with #.');
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_view().
*
* Three formatters are implemented:
* - colorfield_colored_message outputs a configurable message in the color
* filled by the user, the user can use @code in the message to display
* the value of the color.
* - colorfield_raw_rgb displays the raw value of the color, can be used
* to insert the colors in views for instance.
* - colorfield_color_swatch displays a swatch of the configured color, the
* size of the swatch is configurable.
*
* @see colorfield_field_formatter_info()
*/
function colorfield_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
switch ($display['type']) {
// This formatter simply outputs the field as text and with a color.
case 'colorfield_colored_message':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'colorfield_colored_message',
'#text_color' => $item['rgb'],
'#text_message' => t($display['settings']['message'], array(
'@code' => $item['rgb'],
)),
);
}
break;
// This formatter simply outputs the raw RGB value prefixed or not with
// the hash.
case 'colorfield_raw_rgb':
foreach ($items as $delta => $item) {
$color = $display['settings']['display_hash'] ? $item['rgb'] : substr($item['rgb'], 1);
$element[$delta] = array(
'#markup' => $color,
);
}
break;
// Adds an empty DIV, the background of which uses the selected color.
// Could be used, for example, to display a swatch of the color.
case 'colorfield_color_swatch':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '',
'#attributes' => array(
'class' => array(
'colorfield-color-swatch',
),
'style' => 'width: ' . $display['settings']['width'] . 'px; height: ' . $display['settings']['height'] . 'px; background-color:' . $item['rgb'] . ';',
),
);
}
break;
}
return $element;
}
/**
* Implements hook_field_widget_info().
*
* Two widgets are provided:
* - colorfield_unified_textfield lets the user input a color code in
* hexadecimal, the user can do it with a selectable color picker
* (farbtastic or minicolors for instance).
* - colorfield_split_textfield exposes three textfields to the user, one for
* each color component (red, green and blue).
*/
function colorfield_field_widget_info() {
return array(
'colorfield_unified_textfield' => array(
'label' => t('Color code (eg: #FFAA77)'),
'field types' => array(
'colorfield',
),
'settings' => array(
'colorfield_options' => array(
'colorfield_enable_colorpicker' => TRUE,
'colorfield_colorpicker_type' => 'farbtastic',
),
),
'weight' => 0,
),
'colorfield_split_textfield' => array(
'label' => t('Split hex code text based on RGB (eg: FF AA 77)'),
'field types' => array(
'colorfield',
),
'weight' => 1,
),
);
}
/**
* Implements hook_field_widget_form().
*/
function colorfield_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$widget = $element;
$widget['#delta'] = $delta;
switch ($instance['widget']['type']) {
case 'colorfield_unified_textfield':
$value = isset($items[$delta]['rgb']) ? $items[$delta]['rgb'] : '';
$widget += array(
'#type' => 'textfield',
'#default_value' => $value,
'#size' => 7,
'#maxlength' => 7,
);
// Prepare the base markup for the color picker if enabled.
if ($instance['widget']['settings']['colorfield_options']['colorfield_enable_colorpicker']) {
$widget += array(
'#suffix' => '<div class="colorfield-picker"></div>',
'#attributes' => array(
'class' => array(
'colorfield-colorpicker',
),
),
);
// Attach Farbtastic color picker when it's the color picker selected.
if ($instance['widget']['settings']['colorfield_options']['colorfield_colorpicker_type'] == 'farbtastic') {
$widget['#attached'] = array(
'library' => array(
array(
'system',
'farbtastic',
),
),
'js' => array(
drupal_get_path('module', 'colorfield') . '/js/colorfield-farbtastic.js',
),
);
}
}
break;
case 'colorfield_split_textfield':
// If we have a value for this field delta.
// If we don't, just consider empty strings as the default value.
if (isset($items[$delta]['rgb'])) {
$color = $items[$delta]['rgb'];
// Then if the color value is a string we need to split it. It happens
// when the form is submitted (check the hook_field_presave()).
// We don't have a string if the field comes from the default value
// of the field settings. (Ask core maintainers why...).
if (is_string($items[$delta]['rgb'])) {
if (strlen($color) == '7') {
$raw_value = substr($color, 1);
$color = array(
'r' => $raw_value[0] . $raw_value[1],
'g' => $raw_value[2] . $raw_value[3],
'b' => $raw_value[4] . $raw_value[5],
);
}
}
}
else {
$color = array(
'r' => '',
'g' => '',
'b' => '',
);
}
// Make this a fieldset with the three text fields.
$widget += array(
'#type' => 'fieldset',
'#attached' => array(
'css' => array(
drupal_get_path('module', 'colorfield') . '/styles/colorfield.css',
),
),
'#suffix' => '<div class="clearfix"></div>',
'#attributes' => array(
'class' => array(
'colorfield-split-field',
),
),
);
$widget['#title'] = t('Select your color');
$widget['#description'] = '<p>' . t('The 2-digit hexadecimal representation of the color saturation, like "44", "C2" or "FF".') . '</p>';
// Create a textfield for saturation values for Red, Green, and Blue.
foreach (array(
'r' => t('Red'),
'g' => t('Green'),
'b' => t('Blue'),
) as $key => $title) {
$widget[$key] = array(
'#type' => 'textfield',
'#title' => $title,
'#size' => 2,
'#maxlength' => 2,
'#default_value' => $color[$key],
);
}
break;
}
$element['rgb'] = $widget;
return $element;
}
/**
* Implements hook_field_widget_settings_form().
*/
function colorfield_field_widget_settings_form($field, $instance) {
$form = array();
$widget = $instance['widget'];
$settings = $instance['settings'];
if ($widget['type'] == 'colorfield_unified_textfield') {
$form['colorfield_options'] = array(
'#type' => 'fieldset',
'#title' => t('Color selection options'),
);
$default_value_colorpicker = isset($widget['settings']['colorfield_options']['colorfield_enable_colorpicker']) ? $widget['settings']['colorfield_options']['colorfield_enable_colorpicker'] : $settings['colorfield_options']['colorfield_enable_colorpicker'];
$form['colorfield_options']['colorfield_enable_colorpicker'] = array(
'#type' => 'checkbox',
'#title' => t('Enable the color picker.'),
'#description' => t('If you enable this option the user will be able to select a color via a user friendly widget.'),
'#default_value' => $default_value_colorpicker,
);
$default_value_colorpicker_type = isset($widget['settings']['colorfield_options']['colorfield_colorpicker_type']) ? $widget['settings']['colorfield_options']['colorfield_colorpicker_type'] : $settings['colorfield_options']['colorfield_colorpicker_type'];
$form['colorfield_options']['colorfield_colorpicker_type'] = array(
'#type' => 'select',
'#title' => t('Select the color picker'),
'#options' => array(
'farbtastic' => t('Farbtastic'),
),
'#states' => array(
'invisible' => array(
'input[name="instance[widget][settings][colorfield_options][colorfield_enable_colorpicker]"]' => array(
'checked' => FALSE,
),
),
),
'#description' => t('If you are using jQuery 1.7 or a more recent version (via jQuery update), you will expose the !minicolor_link color picker.', array(
'!minicolor_link' => l(t('jQuery Minicolor'), 'https://github.com/claviska/jquery-miniColors'),
)),
'#default_value' => $default_value_colorpicker_type,
);
}
return $form;
}
/**
* Implements hook_feeds_processor_targets_alter().
*/
function colorfield_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
$info = field_info_field($name);
if (in_array($info['type'], array(
'colorfield',
))) {
$targets[$name] = array(
'name' => $instance['label'],
'callback' => 'colorfield_feeds_set_target',
);
}
}
}
/**
* Implements hook_feeds_set_target().
*/
function colorfield_feeds_set_target($source, $entity, $target, $feed_element) {
if (empty($feed_element)) {
return;
}
if (!is_array($feed_element)) {
$feed_element = array(
$feed_element,
);
}
$info = field_info_field($target);
// Iterate over all values.
$field = isset($entity->{$target}) ? $entity->{$target} : array(
$entity->language => array(),
);
// Allow for multiple mappings to the same target.
$delta = count($field[$entity->language]);
foreach ($feed_element as $f) {
if ($info['cardinality'] == $delta) {
break;
}
if (is_object($f) && $f instanceof FeedsElement) {
$f = $f
->getValue();
}
if (is_scalar($f)) {
$field[$entity->language][$delta]['rgb'] = $f;
$delta++;
}
}
$entity->{$target} = $field;
}