Модуль для добавления нового способа отображения в Display Fields для модуля TableField
Пишу модуль для добавления нового способа отображения (для настройки в Display Fields) для модуля TableField без вмешательства в его исходный код.
Цель написания материала: запомнить для себя на будущее и не потерять, получение конструктивной критики, помощь народу, который вдруг сюда зайдёт в поисках похожего решения. Возможно ещё хочу тупо выпендриться :)
Исходные данные
- Есть модуль TableField
- Drupal 6
- Нужно сделать для некоторых из табличных полей свой способ отображения на сайте, который заключается в наличии гламурной кнопочки "покажи мне ещё", при нажатии на которую будет выводится дополнительная строка таблички с каким-то более подробным описанием чего-либо с применением JavaScript.
Приступаю к написанию модуля
Первым делом качаю самую свежую версию и смотрю как отреагировали разработчики на мою попытку запостить баг при работе с модулем Content Complete (кто не использует этот модуль смело забиваем на окончание этого абзаца).
Естественно не отреагировали :( Поэтому я беру свой код из баг репорта и втягиваю к себе, предварительно убедившись, что Content complete всё так-же корректно не работает. Попутно завожу себе напоминалку при апдэйте проверять модуль на фикс данного бага.
Анализ задачи и способа её решния, постановка себя на рельсы
Лёгкое гугление и курение исходников по адресу sites/all/modules/tablefield, показало, что нужно дописать свой хук hook_field_formatter_info, который подсунет допольнительный formatter для вывода полей типа tablefield и повесит на него свой обработчик.
Для хранения дополнительных данных для поля more info решаю использовать последнюю ячейку в каждой строке. Если она пустая, то кнопка "Покажи ещё" не выводится, если не пустая, то выводится во второй ячейке слева (так надо по дизайну).
В обработчике нужно будет переколбасить данные для таблицы так, что-бы они замечательно зашли в функцию theme('table', blah-blah-blah), которую в конечном итоге использует модуль tablefield для вывода таблицы.
Следом иду в admin/build/modules/list и придумываю своему модулю кошерное имя. Мой модуль будет называться tablefield_more и относиться к CCK.
Реализация
Создаю рыбу модуля для Drupal:
- Создаю папку для своего модуля - tablefield_more
- Создаю файл с описанием модуля - tablefield_more.info
- Создаю пустой файл, где будет происходить всё таинство: tablefield_more.module
Пишу собственно модуль:
1. Добиваюсь появления нужно мне форматтера с работающим обработчиком:
Пишу хуки hook_theme, hook_field_formatter_info и рыбу функции темизации вывода.
Включаю свой модуль в admin/build/modules/list, включаю для нужного мне tablefield в admin/content/node-type/[content-type]/display "Tabular View with More info button" вместо "Tabular View"
Проверяю, чтобы на странице материала появился дебаг и тихо радуюсь результату :)
Вот минимальный код модуля, который делает вышеописанное:
<?php
/**
* @file
* This module provides a additional formatter
* for tablefield module
*/
/**
* Implementation of hook_theme().
*/
function tablefield_more_theme() {
return array(
'tablefield_more_formatter_more' => array(
'arguments' => array(
'element' => NULL,
),
),
);
}
/**
* Implementation of hook_field_formatter_info().
*/
function tablefield_more_field_formatter_info() {
return array(
'more' => array(
'label' => t('Tabular View with More info button'),
'multiple values' => CONTENT_HANDLE_CORE,
'field types' => array('tablefield'),
),
);
}
/**
* Theme function for more table display
*/
function theme_tablefield_more_formatter_more($element) {
echo '<pre>';
print_r($element['#item']);
echo '</pre>';
return $element['#item']['value'];
}
2. Усугубляю модуль до нужного функционала:
Как выяснилось в процессе написания, модуль tablefield херит данные в обрабатываемом виде и подменяет их темизованными в функции hook_field на этапе sanitize. И, т.к. мне не удалось в разумные сроки влезть в данные до этого этапа, пришлось применить небольшие грабельки в виде node_load() в форматере поля.
Следом добавляю немножно JavaScript для разворачивания/сворачивания строки с дополнительной информацией. Поскольку на моём сайте активно используется jQuery и он живёт в Core D6, то колбашу фичу под jQuery.
На выходе получилась вот такая конструкция:
tablefield_more.info
name = TableField More
description = Add Formatter with More info button for TableField
dependencies[] = content
dependencies[] = tablefield
package = CCK
core = 6.x
version = "6.x-2.1"
tablefield_more.css
.tablefield span.more_info{ display:block; width:12px; height:12px; background:url(./more_info_bg.gif) no-repeat top left; cursor:pointer; } .tablefield span.selected{ background-position:top right; } .tablefield tr.more_info{ display:none; }
tablefield_more.js
$(document).ready(function(){ $('.tablefield span.more_info').toggle( function() { $(this).addClass("selected"); $(this).parent().parent().next().css('display','table-row'); }, function() { $(this).removeClass("selected"); $(this).parent().parent().next().css('display','none'); } ); });
tablefield_more.module
<?php /** * @file * This module provides a additional formatter * for tablefield module */ /** * Implementation of hook_theme(). */ function tablefield_more_theme() { return array( 'tablefield_more_formatter_more' => array( 'arguments' => array( 'element' => NULL, ), ), ); } /** * Implementation of hook_field_formatter_info(). */ function tablefield_more_field_formatter_info() { return array( 'more' => array( 'label' => t('Tabular View with More info button'), 'multiple values' => CONTENT_HANDLE_CORE, 'field types' => array('tablefield'), ), ); } /** * Theme function for more table display */ function theme_tablefield_more_formatter_more($element) { $delta=$element['#item']['#delta']; $format=$element['#item']['format']; if(isset($element['#item']['tabledata'])){ $tabledata=$element['#item']['tabledata']; $field=$element['#node']->$element['#field_name']; }else{ $node=node_load($element['#node']->nid); $field=$node->$element['#field_name']; $tabledata=unserialize($field[$delta]['value']); $tabledata=tablefield_rationalize_table($tabledata); unset($node); } if (isset($tabledata)) { $table=array(); $addon_rows=0; if (!empty($tabledata)) { drupal_add_css(drupal_get_path('module', 'tablefield_more') . '/tablefield_more.css','module','screen'); drupal_add_js(drupal_get_path('module', 'tablefield_more') . '/tablefield_more.js','theme'); $last_cell=count($tabledata[0])-1; $add_rows=0; foreach ($tabledata as $row_key => $row) { $next_row_data=''; $add_cells=0; if(!empty($row[$last_cell])){ $next_row_data=$row[$last_cell]; } foreach ($row as $col_key => $cell) { if ($col_key<$last_cell){ //ignore last cell if (!empty($field['cell_processing'])) { $table[$row_key+$add_rows][$col_key+$add_cells] = array( 'data' => check_markup($cell, $format), 'class' => 'row-' . ($row_key + $add_rows) . ' col-' . ($col_key + $add_cells) ); }else{ $table[$row_key+$add_rows][$col_key+$add_cells] = array( 'data' => check_plain($cell), 'class' => 'row-' . ($row_key + $add_rows) . ' col-' . ($col_key + $add_cells) ); } if($col_key==0){ //first cell processed, adding more info cell $add_cells++; $table[$row_key+$add_rows][$col_key+$add_cells] = array( 'data' => (empty($next_row_data)?'':'<span class="more_info"></span>'), 'class' => 'more_info row-' . ($row_key + $add_rows) . ' col-' . ($col_key + $add_cells) ); } } } if(!empty($next_row_data)){ //adding more info row $add_rows++; $table[$row_key+$add_rows]=array('data'=>array(),'class'=>'more_info'); if (!empty($field['cell_processing'])) { $table[$row_key+$add_rows]['data'][0] = array( 'data' => check_markup($next_row_data, $format), 'class' => 'row-' . ($row_key + $add_rows) . ' col-0', 'colspan' => ($last_cell+1) ); }else{ $table[$row_key+$add_rows]['data'][0] = array( 'data' => check_plain($next_row_data), 'class' => 'row-' . ($row_key + $add_rows) . ' col-0', 'colspan' => ($last_cell+1) ); } } } } $element['#item']['value'] = theme('tablefield_view', array(), $table, $element['#field_name'], $delta); } return $element['#item']['value']; }
Плюс more_info_bg.gif - картинка размером 24x12px, где слева иконка для разворачивания поля (12x12px) и справа иконка для сворачивания (12х12px)
Скачать модуль tablefield_more (бесплатно, бетта первой версии).
Итого
Пример сделать очень красивым не получилось - пока окончательно не ясно как работают некоторые части друпала. Но общее понятие, как я это сделал, для применения в будущих проектах, пожалуй, создалось. Совсем не плохо было-бы сделать без node_load() в форматере, но это доделаю когда позволит экспиренс или комментарий в тему.
Жду отзывов! Если с вашей точки зрения получился полный отстой, то просьба уточнять что именно не так - критика приветствуется и исправления принимаются.




Обзор AgeStar NSB3AS1T NAS для 3.5" SATA HDD
Комментариев и оценок: 183
Обзор AgeStar NSB3AS1T NAS для 3.5" SATA HDD - сетевого хранилища на базе 3.5" SATA HDD с возможностью подключения по USB. 10/100 Mbit, SATA 3.5"
AgeStar FUBCP USB2.0 to IDE/SATA Adapter
Комментариев и оценок: 93
AgeStar FUBCP - подключение IDE или SATA 2.5",3.5" или 5.25" устройств через USB
Обзор жесткого диска HDD 2ТБ Western Digital WD20EARS
Комментариев и оценок: 73
Краткий обзор жесткого диска HDD 2ТБ Western Digital WD20EARS-00MVWB0 с фотографиями и тестами производительности.Многофункциональное устройство Canon LaserBase MF3228
Комментариев и оценок: 52
Многофункциональное устройство Canon LaserBase MF3228. Описание, впечатления от работы, ссылка на драйвера.
AgeStar SUB2O1 2.5" SATA External Enclosure
Комментариев и оценок: 51
Обзор с картинками и тестами AgeStar SUB201 - внешней USB коробки для 2.5" SATA винчестеров.