field_collection_tabs_widget.module in Field collection tabs widget 7
Provides widget for field collections on tabs
File
field_collection_tabs_widget.moduleView source
<?php
/**
* @file
* Provides widget for field collections on tabs
*/
/**
* Implements hook_field_formatter_info().
*/
function field_collection_tabs_widget_field_widget_info() {
return array(
'field_collection_tabs' => array(
'label' => t('Tabs'),
'description' => t('Field collection form elements as tabs'),
'field types' => array(
'field_collection',
),
'settings' => array(
'fctw_title_field' => 0,
'fctw_title_field_formatter' => 'default',
'fctw_new_tab_title' => 'New',
'fctw_empty_tab_title' => '- None -',
'fctw_add_new_tab_title' => '+',
'fctw_add_new_tab_hover' => 'Add a new tab',
'fctw_hide_first_blank_tab' => FALSE,
),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_DEFAULT,
'default value' => FIELD_BEHAVIOR_NONE,
),
),
);
}
/**
* Implements hook_field_formatter_settings_form().
*/
function field_collection_tabs_widget_field_widget_settings_form($field, $instance) {
// The field settings infrastructure is not AJAX enabled by default,
// because it doesn't pass over the $form_state.
// Build the whole form into a #process in which we actually have access
// to the form state. Idea stolen from entityreference.
$form['settings'] = array(
'#type' => 'container',
'#tree' => TRUE,
'#process' => array(
'_fctw_form_process_merge_parent',
'_fctw_widget_settings_process',
),
'#element_validate' => array(
'_fctw_widget_settings_validate',
),
'#field' => $field,
'#instance' => $instance,
);
return $form;
}
/**
* Widget settings form process callback.
*/
function _fctw_form_process_merge_parent($element) {
$parents = $element['#parents'];
array_pop($parents);
$element['#parents'] = $parents;
return $element;
}
/**
* Widget settings form process callback.
*/
function _fctw_widget_settings_process($element, $form_state) {
$field = $element['#field'];
$instance = $element['#instance'];
$settings = $instance['widget']['settings'];
$element['fctw_new_tab_title'] = array(
'#type' => 'textfield',
'#title' => t('Text to use on a new tab'),
'#default_value' => $settings['fctw_new_tab_title'],
'#size' => 10,
'#maxlength' => 30,
);
$element['fctw_add_new_tab_title'] = array(
'#type' => 'textfield',
'#title' => t('Text to use on the "add a new tab" tab'),
'#default_value' => $settings['fctw_add_new_tab_title'],
'#size' => 10,
'#maxlength' => 30,
);
$element['fctw_add_new_tab_hover'] = array(
'#type' => 'textfield',
'#title' => t('Text to use on the "add a new tab" tab hover'),
'#default_value' => $settings['fctw_add_new_tab_hover'],
'#size' => 10,
'#maxlength' => 30,
);
$element['fctw_hide_first_blank_tab'] = array(
'#type' => 'checkbox',
'#title' => t('Hide first blank tab'),
'#description' => t('If checked, the first blank field collection tab does not appear on form load but only when the "Add a new tab" tab is clicked.'),
'#default_value' => $settings['fctw_hide_first_blank_tab'],
);
$options = array(
t('No titles'),
);
$fields = field_info_instances('field_collection_item', $field['field_name']);
foreach ($fields as $field_name => $field) {
$options[$field_name] = $field['label'];
}
$id = 'fctw-title-field-formatter';
$element['fctw_title_field'] = array(
'#type' => 'select',
'#title' => t('Field to use for tab titles'),
'#default_value' => $settings['fctw_title_field'],
'#options' => $options,
'#ajax' => array(
'callback' => 'fctw_title_field_ajax_callback',
'wrapper' => $id,
'element' => $element['#array_parents'],
),
);
$element['fctw_empty_tab_title'] = array(
'#type' => 'textfield',
'#title' => t('Text to use if the field is empty'),
'#default_value' => $settings['fctw_empty_tab_title'],
'#size' => 10,
'#maxlength' => 30,
);
$element['fctw_title_field']['#ajax']['element'][] = 'fctw_title_field_formatter';
if (isset($form_state['input']['_triggering_element_name']) && $form_state['input']['_triggering_element_name'] == 'instance[widget][settings][fctw_title_field]') {
$title_field = $form_state['input']['instance']['widget']['settings']['fctw_title_field'];
}
else {
$title_field = $element['fctw_title_field']['#default_value'];
}
if ($title_field) {
$field_type = field_info_field($title_field);
$field_type = $field_type['type'];
$formatter_options = field_ui_formatter_options($field_type);
$element['fctw_title_field_formatter'] = array(
'#type' => 'select',
'#title' => t('Formatter'),
'#options' => $formatter_options,
'#prefix' => '<div id="' . $id . '">',
'#suffix' => '</div>',
);
if (empty($form_state['input']['_triggering_element_name']) && empty($form_state['triggering_element'])) {
$element['fctw_title_field_formatter']['#default_value'] = $settings['fctw_title_field_formatter'];
}
else {
$keys = array_keys($formatter_options);
$element['fctw_title_field_formatter']['#default_value'] = reset($keys);
$element['fctw_title_field_formatter']['#value'] = reset($keys);
}
}
else {
$element['fctw_title_field_formatter'] = array(
'#prefix' => '<div id="' . $id . '">',
'#suffix' => '</div>',
);
}
return $element;
}
/**
* AJAX callback for the widget settings form.
*/
function fctw_title_field_ajax_callback($form, $form_state) {
$trigger = $form_state['triggering_element'];
$key_exists = NULL;
$return = drupal_array_get_nested_value($form, $trigger['#ajax']['element'], $key_exists);
if ($key_exists) {
return $return;
}
else {
array_shift($trigger['#ajax']['element']);
return drupal_array_get_nested_value($form, $trigger['#ajax']['element'], $key_exists);
}
}
/**
* Validate callback for the widget settings form.
*/
function _fctw_widget_settings_validate($form, &$form_state) {
if (!isset($form_state['values']['instance']['widget']['settings']['fctw_title_field_formatter']) && isset($form_state['input']['instance']['widget']['settings']['fctw_title_field_formatter'])) {
$form_state['values']['instance']['widget']['settings']['fctw_title_field_formatter'] = $form_state['input']['instance']['widget']['settings']['fctw_title_field_formatter'];
}
}
/**
* Implements hook_field_widget_form().
*/
function field_collection_tabs_widget_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$instance['widget']['type'] = 'field_collection_embed';
$element = field_collection_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);
return $element;
}
/**
* Implements hook_theme_registry_alter().
*
* We want our own version of field_multiple_value_form().
*/
function field_collection_tabs_widget_theme_registry_alter(&$theme_registry) {
$theme_registry['field_multiple_value_form']['function'] = 'theme_field_collection_tabs_widget_field_multiple_value_form';
}
/**
* Implements hook_theme().
*/
function field_collection_tabs_widget_theme($existing, $type, $theme, $path) {
return array(
'fctw_item_list' => array(
'variables' => array(
'items' => array(),
'title' => NULL,
'type' => 'ul',
'attributes' => array(),
),
),
'fctw_add_new_tab' => array(
'variables' => array(
'instance' => array(),
),
),
);
}
/**
* Implements hook_field_widget_form_alter().
*/
function field_collection_tabs_widget_field_widget_form_alter(&$element, &$form_state, $context) {
$element['#instance'] = $context['instance'];
// Display Suite forms support.
if (module_exists('ds_forms')) {
if ($ds_form = ds_build_load($element, 'field_collection_tabs')) {
// Use ds_forms_custom_form theme only for field_collections.
if (isset($element['#instance']['widget']['module']) && $element['#instance']['widget']['module'] == 'field_collection_tabs_widget') {
if ($layout = ds_get_layout($ds_form->entity_type, $ds_form->bundle, 'form', FALSE)) {
// Add the theming function and add the layout as a class.
$element['#theme'] = array(
'ds_forms_custom_form',
);
$element['#form_id'] = 'field_collection_tabs';
$class = strtr($layout['layout'], '_', '-');
if (isset($element['#attributes']['class']) && is_array($element['#attributes']['class']) || !isset($element['#attributes']['class'])) {
$element['#attributes']['class'][] = $class;
}
elseif (isset($element['#attributes']['class']) && is_string($element['#attributes']['class'])) {
$element['#attributes']['class'] .= ' ' . $class . ' ';
}
}
}
}
}
}
/**
* Implements hook_libraries_info().
*/
function field_collection_tabs_widget_libraries_info() {
$library_path = libraries_get_path('erta');
$libraries['erta'] = array(
'name' => 'Easy Responsve Tabs to Accordion plugin',
'vendor url' => 'https://github.com/samsono/Easy-Responsive-Tabs-to-Accordion',
'download url' => 'https://github.com/samsono/Easy-Responsive-Tabs-to-Accordion/archive/master.zip',
'version arguments' => array(
'file' => 'Easy-Responsive-Tabs-to-Accordion.jquery.json',
'pattern' => '@"version": "([0-9\\.a-z]+)"@',
'lines' => 5,
),
'files' => array(
'js' => array(
'js/easyResponsiveTabs.js',
),
'css' => array(
'css/easy-responsive-tabs.css',
),
),
);
return $libraries;
}
/**
* Implements hook_requirements().
*/
function field_collection_tabs_widget_requirements($phase) {
$t = get_t();
$requirements = array();
$requirements['erta'] = array(
'title' => $t('Easy Responsive Tabs to Accordion version'),
);
$erta = libraries_load('erta');
if (!$erta['installed']) {
$requirements['erta']['value'] = $t('Not installed');
$requirements['erta']['description'] = $t('Easy Responsive Tabs to Accordion is not installed.');
$requirements['erta']['severity'] = REQUIREMENT_ERROR;
}
elseif (version_compare($erta['version'], '1.2.1') < 0) {
$requirements['erta']['value'] = $erta['version'];
$requirements['erta']['description'] = $t('Easy Responsive Tabs to Accordion version is lower than 1.2.1.');
$requirements['erta']['severity'] = REQUIREMENT_ERROR;
}
else {
$requirements['erta']['value'] = $erta['version'];
}
return $requirements;
}
/**
* Theme function for generating an item list.
*
* Completely identical to theme_item_list() apart from the
* item-list wrapper.
*/
function theme_fctw_item_list($variables) {
$items = $variables['items'];
$title = $variables['title'];
$type = $variables['type'];
$attributes = $variables['attributes'];
$output = '';
// Only output the list container and title, if there are any list items.
// Check to see whether the block title exists before adding a header.
// Empty headers are not semantic and present accessibility challenges.
if (isset($title) && $title !== '') {
$output .= '<h3>' . $title . '</h3>';
}
if (!empty($items)) {
$output .= "<{$type}" . drupal_attributes($attributes) . '>';
$num_items = count($items);
$i = 0;
foreach ($items as $item) {
$attributes = array();
$children = array();
$data = '';
$i++;
if (is_array($item)) {
foreach ($item as $key => $value) {
if ($key == 'data') {
$data = $value;
}
elseif ($key == 'children') {
$children = $value;
}
else {
$attributes[$key] = $value;
}
}
}
else {
$data = $item;
}
if (count($children) > 0) {
// Render nested list.
$data .= theme_item_list(array(
'items' => $children,
'title' => NULL,
'type' => $type,
'attributes' => $attributes,
));
}
if ($i == 1) {
$attributes['class'][] = 'first';
}
if ($i == $num_items) {
$attributes['class'][] = 'last';
if (strpos($item, 'add-more_button')) {
$attributes['class'][] = 'add-more';
}
}
$output .= '<li' . drupal_attributes($attributes) . '>' . $data . "</li>\n";
}
$output .= "</{$type}>";
}
return $output;
}
/**
* Implements hook_field_attach_form().
*
* Applies field_collection_field_attach_form() to field_collection_tabs and
* extends it with a modified
* https://www.drupal.org/files/field_collection-allow-add-another-1788222-12.patch.
*/
function field_collection_tabs_widget_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
foreach (field_info_instances($entity_type, $form['#bundle']) as $field_name => $instance) {
$field = field_info_field($field_name);
if ($field['type'] == 'field_collection' && $instance['widget']['type'] == 'field_collection_tabs' && field_access('edit', $field, $entity_type)) {
if ($field['settings']['hide_blank_items']) {
$element_langcode = $form[$field_name]['#language'];
if ($form[$field_name][$element_langcode]['#max_delta'] > 0) {
$form[$field_name][$element_langcode]['#max_delta']--;
}
$form[$field_name][$element_langcode]['#instance'] = $instance;
// Force user to explicitly add a fc.
if (!empty($instance['widget']['settings']['fctw_hide_first_blank_tab']) && !isset($form[$field_name][$element_langcode][0]['#entity']->item_id)) {
unset($form[$field_name][$element_langcode][0]);
unset($form_state['field']['#parents'][$field_name][$element_langcode][0]);
}
}
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
$element_langcode = $form[$field_name]['#language'];
$element_wrapper = $form[$field_name][$element_langcode]['add_more']['#ajax']['wrapper'];
for ($i = 0; $i <= $form[$field_name][$element_langcode]['#max_delta']; $i++) {
if (isset($form[$field_name][$element_langcode][$i]['remove_button'])) {
$form[$field_name][$element_langcode][$i]['remove_button']['#ajax']['wrapper'] = $element_wrapper;
}
}
}
}
}
}
/**
* Replacement for theme_field_multiple_value_form().
*/
function theme_field_collection_tabs_widget_field_multiple_value_form($variables) {
$element = $variables['element'];
$output = '';
if (isset($element['#instance']) && $element['#instance']['widget']['type'] == 'field_collection_tabs') {
$instance = $element['#instance'];
if (isset($element['#cardinality']) && ($element['#cardinality'] > 1 || $element['#cardinality'] == FIELD_CARDINALITY_UNLIMITED)) {
$title_field = $instance['widget']['settings']['fctw_title_field'];
$id = drupal_html_id($element['#field_name'] . '_values');
$required = !empty($element['#required']) ? '<span class="form-required" title="' . t('This field is required. ') . '">*</span>' : '';
$resp_tabs_list = array();
$resp_tabs_container = array();
// Sort items according to '_weight' (needed when the form comes back after
// preview or failed validation)
$items = array();
foreach (element_children($element) as $key) {
if ($key === 'add_more') {
$add_more_button =& $element[$key];
$add_more_button['#attributes']['style'] = 'display: none';
}
else {
$items[] =& $element[$key];
}
}
usort($items, '_field_sort_items_value_helper');
// Add the items as list rows.
foreach ($items as $key => $item) {
if (!isset($item['#entity'])) {
continue;
}
$title = field_get_items('field_collection_item', $item['#entity'], $title_field);
// This is a new field collection
$string_name = 'fctw:' . $instance['entity_type'] . ':' . $instance['bundle'] . ':' . $instance['field_name'];
if (!isset($title) || empty($item['#entity']->item_id)) {
$title = fctw_t($string_name . ':new_tab_title', $instance['widget']['settings']['fctw_new_tab_title']);
}
else {
$display = array(
'label' => 'hidden',
'type' => $instance['widget']['settings']['fctw_title_field_formatter'],
);
$title = field_view_field($item['#entity_type'], $item['#entity'], $title_field, $display);
$title = drupal_render($title);
}
// If the title field is empty use the default text.
if (empty($title)) {
$title = fctw_t($string_name . ':empty_tab_title', $instance['widget']['settings']['fctw_empty_tab_title']);
}
// Tab text
$resp_tabs_list[] = $title;
// Tab contents
$item['_weight']['#attributes']['class'][] = 'fctw-weight';
$resp_tabs_container[] = array(
'fc_form' => array(
'#type' => 'container',
'#attributes' => array(),
'item' => $item,
),
);
}
// Adding the "Add a new tab" tab.
if (!empty($add_more_button)) {
$resp_tabs_list[] = theme('fctw_add_new_tab', array(
'instance' => $instance,
));
$resp_tabs_container[] = array(
'fc_form' => array(
'#type' => 'container',
'#attributes' => array(),
'item' => $add_more_button,
),
);
}
// We add the id of the whole fc widget to Drupal.settings to
// call easyResponsiveTabs() on them.
$id = drupal_html_id('fctw');
drupal_add_js(array(
'fieldCollectionTabsWidgetIds' => array(
$id,
),
), 'setting');
// Adding necessary javascript to do the magic.
libraries_load('erta');
drupal_add_library('system', 'ui.sortable');
drupal_add_js(drupal_get_path('module', 'field_collection_tabs_widget') . '/field_collection_tabs_widget.js');
drupal_add_css(drupal_get_path('module', 'field_collection_tabs_widget') . '/field_collection_tabs_widget.css');
$output = array(
'#type' => 'container',
'#attributes' => array(
'id' => $id,
),
'label' => array(
'#type' => 'markup',
'#markup' => '<label>' . t('!title !required', array(
'!title' => $element['#title'],
'!required' => $required,
)) . '</label>',
),
'tabs' => array(
'#theme' => 'fctw_item_list',
'#type' => 'ul',
'#items' => $resp_tabs_list,
'#attributes' => array(
'class' => array(
'resp-tabs-list',
),
),
),
'resp_tabs_container' => array(
'#type' => 'container',
'#attributes' => array(
'class' => array(
'resp-tabs-container',
),
),
'rtc' => $resp_tabs_container,
),
);
$output = drupal_render($output);
}
else {
foreach (element_children($element) as $key) {
$output .= drupal_render($element[$key]);
}
}
}
else {
// Cannot use theme() here because of field_collection_tabs_widget_theme_registry_alter().
return theme_field_multiple_value_form($variables);
}
return $output;
}
/**
* Theme function to theme the "Add a new tab" tab.
*/
function theme_fctw_add_new_tab(&$variables) {
$instance = $variables['instance'];
$name = 'fctw:' . $instance['entity_type'] . ':' . $instance['bundle'] . ':' . $instance['field_name'];
return '<div class="add-more_button" title="' . fctw_t($name . ':add_new_tab_hover', $instance['widget']['settings']['fctw_add_new_tab_hover']) . '">' . fctw_t($name . ':add_new_tab_title', $instance['widget']['settings']['fctw_add_new_tab_title']) . '</div>';
}
/**
* Helper function to integrate with the i18n_strings module.
*
* @param string $name
* Textgroup and context glued with ':'.
* @param string $string
* The raw db value for the given property
* @param string $langcode
* Optional language code to override the page requested one.
*/
function fctw_t($name, $string, $langcode = NULL) {
$i18n =& drupal_static(__FUNCTION__);
if (!isset($i18n)) {
$i18n = module_exists('i18n_string');
}
return $i18n ? i18n_string($name, $string, array(
'langcode' => $langcode,
)) : $string;
}
/**
* Implements hook_i18n_string_info().
*/
function field_collection_tabs_widget_i18n_string_info() {
$groups['fctw'] = array(
'title' => t('Field collection tabs widget'),
'description' => t('FCTW strings for localization.'),
'format' => FALSE,
'list' => TRUE,
'refresh callback' => 'field_collection_tabs_widget_i18n_string_refresh',
);
return $groups;
}
/**
* i18n_string callback for refreshing all strings.
*/
function field_collection_tabs_widget_i18n_string_refresh() {
foreach (field_info_instances() as $entity => $bundles) {
foreach ($bundles as $bundle => $field_instances) {
foreach ($field_instances as $field_instance => $settings) {
if ($settings['widget']['type'] == 'field_collection_tabs') {
i18n_string_update("fctw:{$entity}:{$bundle}:{$field_instance}:new_tab_title", $settings['widget']['settings']['fctw_new_tab_title']);
i18n_string_update("fctw:{$entity}:{$bundle}:{$field_instance}:add_new_tab_title", $settings['widget']['settings']['fctw_add_new_tab_title']);
i18n_string_update("fctw:{$entity}:{$bundle}:{$field_instance}:add_new_tab_hover", $settings['widget']['settings']['fctw_add_new_tab_hover']);
i18n_string_update("fctw:{$entity}:{$bundle}:{$field_instance}:empty_tab_title", $settings['widget']['settings']['fctw_empty_tab_title']);
}
}
}
}
return TRUE;
}