Skip to content
Snippets Groups Projects
Commit 98e5db06 authored by Kevin Hankens's avatar Kevin Hankens
Browse files

initial import of tablefield module

parents
No related branches found
No related tags found
No related merge requests found
$Id
README.txt
----------
This module provides a simple, generic form/widget to input tabular data. The form allows the user to select the number or rows/columns in the table, then enter data via textfields. Since this is a CCK field, it is automatically revision capable, multi-value capable and has prebuilt integration with Views.
INSTALLATION
------------
- Copy tablefield directory to /sites/all/modules
- Enable module at /admin/build/modules
- Add a tablefield to a content type at /admin/content/types
AUTHOR/MAINTAINER
-----------------
- Kevin Hankens
- http://www.kevinhankens.com
/* $Id$ */
#content-field-edit-form .node-tablefield .form-text,
.node-form .node-tablefield .form-text {
width: auto;
margin: 1px 1px 1px 1px;
padding: 1px 1px 1px 1px;
}
#content-field-edit-form .node-tablefield .form-item,
.node-form .node-tablefield .form-item {
float: left;
margin: 0 0 0 0;
padding: 0 0 0 0;
}
#content-field-edit-form .node-tablefield table,
.node-form .node-tablefield table {
width: auto;
}
#content-field-edit-form .node-tablefield table tr td,
.node-form .node-tablefield table tr td {
margin: 0 0 0 0;
padding: 0 0 0 0;
}
#content-field-edit-form .node-tablefield .tablefield-rebuild,
.node-form .node-tablefield .tablefield-rebuild {
margin-top: 0.5em;
}
; $Id$
name = TableField
description = Defines a generic tablular data field.
dependencies[] = content
package = CCK
core = 6.x
<?php
// $Id$
/**
* @file
* This module provides a set of fields that can be used to store
* tabular data with a node
*/
/**
* Implementation of hook_theme().
*/
function tablefield_theme() {
return array(
'tablefield' => array(
'arguments' => array(
'element' => NULL,
),
),
'tablefield_formatter_default' => array(
'arguments' => array(
'element' => NULL,
),
),
'tablefield_view' => array(
'arguments' => array(
'header' => NULL,
'rows' => NULL,
),
),
);
}
/**
* Implementation of hook_field_info().
*/
function tablefield_field_info() {
return array(
'tablefield' => array(
'label' => t('Table Field'),
'description' => t('Stores a table of text fields'),
),
);
}
/**
* Implementation of hook_field_settings().
*
* @todo build a case for 'views data'
*/
function tablefield_field_settings($op, $field) {
switch ($op) {
case 'form':
$form = array();
$form['count_cols'] = array(
'#type' => 'textfield',
'#title' => t('Default number of columns. This can be overridden in each node.'),
'#element_validate' => array('_element_validate_number'),
'#default_value' => $field['count_cols'],
);
$form['count_rows'] = array(
'#type' => 'textfield',
'#title' => t('Default number of rows. This can be overridden in each node.'),
'#element_validate' => array('_element_validate_number'),
'#default_value' => $field['count_rows'],
);
break;
case 'save':
$values = array('count_cols', 'count_rows');
return $values;
break;
case 'database columns':
return array(
'value' => array('type' => 'text', 'default' => ''),
);
break;
case 'views data':
$data = content_views_field_views_data($field);
return $data;
break;
}
}
/**
* Implementation of hook_field().
*/
function tablefield_field($op, &$node, $field, &$items, $teaser, $page) {
switch ($op) {
case 'presave':
foreach ($items as $delta => $table) {
// Get rid of configuration data sent in form_state
//unset($table['tablefield']['count_rows']);
//unset($table['tablefield']['count_cols']);
//unset($table['tablefield']['rebuild']);
$tablefield = array();
foreach ($table['tablefield'] as $key => $value) {
$tablefield[$key] = $value;
}
$items[$delta]['value'] = serialize($tablefield);
}
break;
case 'load':
foreach ($items as $delta => $table) {
$items[$delta]['tabledata'] = tablefield_rationalize_table(unserialize($table['value']));
}
break;
case 'sanitize':
// We need to make the table data available to display
foreach ($items as $delta => $table) {
if (isset($table['tablefield'])) {
$tabledata = tablefield_rationalize_table($table['tablefield']);
}
elseif (isset($table['value'])) {
$tabledata = tablefield_rationalize_table(unserialize($table['value']));
}
// Pull the header for theming
$header = $tabledata[0];
unset($tabledata[0]);
$items[$delta]['value'] = theme('tablefield_view', $header, $tabledata, $node->nid, $delta);
}
break;
}
}
/**
* Implementation of hook_content_is_empty().
*/
function tablefield_content_is_empty($item, $field) {
// First see if the submitted field matches the default
unset($item['tablefield']['rebuild']);
if ($item['tablefield'] == $field['widget']['default_value'][0]['tablefield']) {
return TRUE;
}
// Remove the preference fields to see if the table cells are all empty
unset($item['tablefield']['count_cols']);
unset($item['tablefield']['count_rows']);
if (!empty($item['tablefield'])) {
foreach ($item['tablefield'] as $cell) {
if (!empty($cell)) {
$empty = FALSE;
return FALSE;
}
}
}
return TRUE;
}
/**
* Implementation of hook_field_formatter_info().
*/
function tablefield_field_formatter_info() {
return array(
'default' => array(
'label' => t('Tabular View'),
'multiple values' => CONTENT_HANDLE_CORE,
'field types' => array('tablefield'),
),
);
}
/**
* Theme function for default table display
*/
function theme_tablefield_formatter_default($element) {
return $element['#item']['value'];
}
/**
* Theme function for form display
*/
function theme_tablefield($element) {
return $element['#children'];
}
/**
* Theme function for table view
*/
function theme_tablefield_view($header, $rows, $nid, $delta) {
return '<div id="tablefield-wrapper-' . $nid . '-' . $delta . '" class="tablefield-wrapper">' . theme('table', $header, $rows, array('id' => 'tablefield-' . $nid . '-' . $delta, 'class' => 'tablefield')) . '</div>';
}
/**
* Implementation of hook_widget_info().
*/
function tablefield_widget_info() {
return array(
'tablefield' => array(
'label' => t('Table field'),
'field types' => array('tablefield'),
'multiple values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
/**
* Implementation of FAPI hook_elements().
*/
function tablefield_elements() {
drupal_add_css(drupal_get_path('module', 'tablefield') . '/tablefield.css');
return array(
'tablefield' => array(
'#input' => TRUE,
'#columns' => array('value'), '#delta' => 0,
'#process' => array('tablefield_process'),
),
);
}
/**
* Implementation of hook_widget().
*
* Attach a single form element to the form. It will be built out and
* validated in the callback(s) listed in hook_elements. We build it
* out in the callbacks rather than here in hook_widget so it can be
* plugged into any module that can provide it with valid
* $field information.
*
* Content module will set the weight, field name and delta values
* for each form element. This is a change from earlier CCK versions
* where the widget managed its own multiple values.
*
* If there are multiple values for this field, the content module will
* call this function as many times as needed.
*
* @param $form
* the entire form array, $form['#node'] holds node information
* @param $form_state
* the form_state, $form_state['values'][$field['field_name']]
* holds the field's form values.
* @param $field
* the field array
* @param $items
* array of default values for this field
* @param $delta
* the order of this item in the array of subelements (0, 1, 2, etc)
*
* @return
* the form item for a single element for this field
*/
function tablefield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element = array(
'#type' => $field['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
);
return $element;
}
/**
* Process the tablefield
*/
function tablefield_process($element, $edit, $form_state, $form) {
$delta = $element['#delta'];
if (isset($element['#value']['tablefield'])) {
// A form was submitted
$default_value = tablefield_rationalize_table($element['#value']['tablefield']);
}
elseif (isset($element['#default_value']['value'])) {
// Default from database
$default_value = tablefield_rationalize_table(unserialize($element['#default_value']['value']));
}
else {
// Get the widget default value
$default_value = tablefield_rationalize_table($form['#field_info'][$element['#field_name']]['widget']['default_value'][0]['tablefield']);
}
$element['tablefield'] = array(
'#title' => t('Data Table'),
'#description' => t('The first row will appear as the table header.'),
'#attributes' => array('id' => 'node-tablefield-' . $delta, 'class' => 'node-tablefield'),
'#type' => 'fieldset',
'#tree' => TRUE,
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#field_name' => $element['#field_name'],
'#type_name' => $element['#type_name'],
'#delta' => $element['#delta'],
'#columns' => $element['#columns'],
);
if ($form['#id'] == 'content-field-edit-form') {
$element['tablefield']['#description'] = t('The first row will appear as the table header. This form defines the table field defaults, but the number of rows/columns and content can be overridden on a per-node basis.');
}
// Determine how many rows/columns are saved in the data
if (!empty($default_value)) {
$count_rows = count($default_value);
foreach ($default_value as $row) {
$temp_count = count($row);
if ($temp_count > $count_cols) {
$count_cols = $temp_count;
}
}
}
else {
$count_cols = 5;
$count_rows = 5;
}
// Override the number of rows/columns if the user rebuilds the form
if (!empty($edit['tablefield']['count_cols'])) {
$count_cols = $edit['tablefield']['count_cols'];
}
if (!empty($edit['tablefield']['count_rows'])) {
$count_rows = $edit['tablefield']['count_rows'];
}
// Render the form table
$element['tablefield']['break' . $i] = array(
'#type' => 'markup',
'#value' => '<table>',
);
for ($i = 0; $i < $count_rows; $i++) {
$element['tablefield']['break' . $i] = array(
'#type' => 'markup',
'#value' => '<tr>',
);
for ($ii = 0; $ii < $count_cols; $ii++) {
$element['tablefield']['cell_' . $i . '_' . $ii] = array(
'#type' => 'textfield',
'#size' => 10,
'#attributes' => array('id' => 'tablefield_' . $delta . '_cell_' . $i . '_' . $ii),
'#default_value' => (empty($field_value)) ? $default_value[$i][$ii] : $field_value,
'#prefix' => '<td>',
'#suffix' => '</td>',
);
}
$element['tablefield']['break' . $i] = array(
'#type' => 'markup',
'#value' => '</tr>',
);
}
$element['tablefield']['break' . $i] = array(
'#type' => 'markup',
'#value' => '</table',
);
// Allow the user to add more rows/columns
$element['tablefield']['count_cols'] = array(
'#title' => t('How many Columns'),
'#type' => 'textfield',
'#size' => 5,
'#prefix' => '<div class="clear-block">',
'#suffix' => '</div>',
'#default_value' => $count_cols,
);
$element['tablefield']['count_rows'] = array(
'#title' => t('How many Rows'),
'#type' => 'textfield',
'#size' => 5,
'#prefix' => '<div class="clear-block">',
'#suffix' => '</div>',
'#default_value' => $count_rows,
);
$element['tablefield']['rebuild'] = array(
'#type' => 'button',
'#value' => t('Rebuild Table'),
'#attributes' => array('class' => 'tablefield-rebuild'),
);
return $element;
}
function tablefield_rationalize_table($tablefield) {
$count_cols = $tablefield['count_cols'];
unset($tablefield['count_cols']);
$count_rows = $tablefield['count_rows'];
unset($tablefield['count_rows']);
unset($tablefield['rebuild']);
// Rationalize the table data
if (!empty($tablefield)) {
foreach ($tablefield as $key => $value) {
preg_match('/cell_(.*)_(.*)/', $key, $cell);
// $cell[1] is row count $cell[2] is col count
if ((int) $cell[1] < $count_rows && $cell['2'] < $count_cols) {
$tabledata[$cell[1]][$cell[2]] = $value;
}
}
}
return $tabledata;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment