
Ввиду повального незнания о возможностях темизации Друпала и использования Form API, большая часть разработчиков лишается возможности делать приятные сайты.
Данная статья призвана возбудить все-таки у людей интерес к использованию средств темизации.
Недавно я был участником дискуссии на тему идеальной формы комментирования. Так вот, помните на что похожа стандартная друпаловская форма комментариев?
Эта форма содержит в себе абсолютно все минусы, которые могут быть. Она громоздка, скучна и непонятна рядовому пользователю.
А на что в действительности способен Друпал?
Для начала, немного теории. Любую форму в пятой версии Друпала можно темизировать создав в файле шаблона template.php функцию phptemplate_FORM_ID($form), где FORM_ID - это идентификатор формы.
Форма комментирования имеет id равный comment-form, поэтому, для нее функция темизации будет называться phptemplate_comment_form:
function phptemplate_comment_form($form) {
}
Если вы все сделали правильно, то после того как вы впишите эту функцию в свой template.php, на сайте сразу пропадут все формы комментирования.
Дальше стоит разобраться, что находится в переменной $form, которая находится в параметрах функции. Вписываем волшебный print_r:
function phptemplate_comment_form($form) {
print_r($form);
}
После этого вы увидите кучу всякого кода сверху экрана. Если посмотреть в исходный код страницы, выглядеть это будет примерно так:
Это и есть массив формы. Справка по каждому из полей.
А теперь, к делу:
function phptemplate_comment_form($form) {
// убираем имя автора (если юзер залогинен)
if ($form['_author'])
unset($form['_author']['#type']);
// убираем все форматы форматирования из формы
unset($form['comment_filter']['format']);
// формируем один единственный формат ввода
// (будет сформирован формат, который выбран в админке по-умолчанию)
// тут же мы избавляемся и от ссылки "Подробнее о форматировании"
// просто не включив ее в состав формы
$form['comment_filter'][1] = array(
'#type' => 'value',
'#value' => variable_get('filter_default_format', 1)
);
$tips = _filter_tips(variable_get('filter_default_format', 1), FALSE);
$form['comment_filter']['format']['guidelines'] = array(
'#title' => t('Formatting guidelines'),
'#value' => theme('filter_tips', $tips, FALSE, $extra),
);
// убираем поле "домашняя страница" с формы
// так как в большинстве случаев оно лишнее
unset($form['homepage']);
// скрываем подпись у главного поля комментирования
$form['comment_filter']['comment']['#title'] = '';
// устанавливаем меньшее количество строк у поля
$form['comment_filter']['comment']['#rows'] = '7';
// это условие спасает нас, в случае залогиненного юзера
// (у залогиненных нет этих полей)
if (($form['mail'])&&($form['name'])) {
// оборачиваем всю правую часть в теги
// ниже, в описании стилей можно увидеть, что класс side
// выравнивается по правому краю
$form['name']['#prefix'] = '<div class="side">';
$form['name']['#suffix'] = '</div>';
$form['mail']['#prefix'] = '<div class="side">';
$form['mail']['#suffix'] = '</div>';
// оборачиваем поле для ввода в свои теги
$form['comment_filter']['#prefix'] = '<div class="main">';
$form['comment_filter']['#suffix'] = '</div>';
}
// оборачиваем в теги надпись о форматировании
// обратите внимание на css свойства класса guidelines
$form['comment_filter']['format']['guidelines']['#prefix'] =
'<div class="guidelines nolink">';
$form['comment_filter']['format']['guidelines']['#suffix'] = '</div>';
//подключаем файл с js-блиотекой на страницу
drupal_add_js(path_to_theme().'/comments.js');
//цепляем вызовы js-функций под код нашей формы
$form['#suffix'] .= '<script type="text/javascript">'.
'insertGuidelinesLink("'.t('What can I enter?').'");'.
'replaceButtons("#comment-form");'.
'</script>';
//выводим форму
$output .= drupal_render($form);
return $output;
}
Для того, чтобы это все работало под Drupal 6, нужно добавить вот такую функцию в template.php или дополнить ее, если она уже существует:
function названиетемы_theme() {
return array(
'comment_form' => array(
'arguments' => array('form' => NULL),
),
);
а функцию темизации обозвать имя_темы_comment_form(). И не забудьте почитить кеш друпала!
// файл comments.js в директории вашей темы
// (создать, если потребуется)
function replaceButtons(form) {
$(form+' .form-submit').each(function(){
id = $(this).attr('id');
text = $(this).attr('value');
$(this).css('display','none');
$(this).after('<a class="'+id+' button form-submit" href="#"><span>'+text+'</span></a>');
$('a.'+id).click(function(){
$('#edit-op').attr('value',$(this).text());
$(form).submit();
return false;
});
});
}
function insertGuidelinesLink(title) {
$('.guidelines.nolink').before('<a href="#" id="guidelink">'+title+'</a>');
$('.guidelines.nolink').removeClass('.nolink');
$('#guidelink').click(function(){
$(this).slideUp('fast');
$('.guidelines').slideDown('fast');
return false;
});
}
.main{
margin:0px 250px 0 0;
}
.side{
width:230px;
float:right;
clear:right;
margin:0 0 10px 0;
}
.main .form-item,.side .form-item{
margin:0;
}
.side input.form-text{
width:100%
}
#guidelink{
font-size:10px;
text-decoration:none;
border-bottom:dashed 1px;
}
.guidelines{
display:none;
margin:10px 0 0;
}
Итого, форма будет выглядеть так:

Красота?
Решение полностью Drupal-правильное, W3C-валидное и кросс-браузерное.
P.S. Cовсем забыл про капчу. Пользуйтесь моей скрытой капчей и будет вам счастье.
См. также Темизация форм (D5-6)
Здорово. А не подскажите можно ли и если можно то как в эту форму добавить авторизацию по openid?
На сколько мне известно, готового решения нет пока. Но, думаю, это тоже реализуемо.
Форматы ввода скрываются и показывается только один - который выбран по умолчанию, а остальные оказываются недоступны...
Это так задумано или всё же ошибка?
Это так задумано. Если это не требуется, никто не заставляет их скрывать. Но в моей практике еще не было сайтов, где стоило оставлять форматы ввода с выбором (разве что для административных аккаунтов), а рядовой юзер их или не замечает или не понимает.
# | miko
Спасибо за интересную статью и красивый дизайн. Долго бьюсь с формой логина, так и не удалось найти способ как ее темизировать, по человечески. Нет ли каких-нибудь мыслей по этому поводу? Буду очень признателен!
Все то же самое. Вот, к примеру, добавление ссылки на "Забыли пароль?" в форму логина:
function phptemplate_user_login($form) {
$form['from'] = array(
'#type' => 'item',
'#value' => l(t('Forgot password?'),'user/password'),
'#weight' => 1,
);
return drupal_render($form);
}
# | miko
Спасибо за оперативный ответ, neochief!
Такой функции я не нашел... В user.module есть user_login_block() собственно там и определяется форма, Насколько я понимаю... но она разве "темабильна"? Я читал где-то, что только theme.... можно оверрайдить в template.php. Это не правда? Я пробовал ее переопределиь, но при этом перестает правильно работать модуль. Например форма постоянно висит на экране, даже если User зашел. Нормальная форма исчезает. Или вообще может не логинится...
... А если почитать внимательно статью, то можно найти такие строки:
Любую форму в пятой версии Друпала можно темизировать создав в файле шаблона template.php функцию phptemplate_FORM_ID($form), где FORM_ID - это идентификатор формы.
Реализация нормальная, но!
Вот, например для вашего сайта это не удобно, т.к. после нажатия таба, попадаешь на форму поиска и + на кнопку поиска, а только потом на формы имени и т.д.
Наконец понял, что вы имеете в виду. Проблему здесь устранил, но в статью добавлять не буду, чтобы не усложнять слишком. Проблема решается помещением дополнительных полей физически под текстовое поле комментария (в статье, они в реальности поверх, поэтому и происходит такой конфуз с tab-order'ом). Это достигается изменением веса этих полей, к примеру:
//$form['comment_filter'] имеет вес меньше еденицы
$form['name']['#weight'] = 1.01;
$form['mail']['#weight'] = 1.02;
$form['homepage']['#weight'] = 1.03;Еще одним способом является установка атрибута tabindex у всех элементов формы, делается это так:
$form['comment_filter']['comment']['#attributes'] = array('tabindex' => '1');
$form['name']['#attributes'] = array('tabindex' => '2');
$form['mail']['#attributes'] = array('tabindex' => '3');
$form['homepage']['#attributes'] = array('tabindex' => '4');
$form['notify']['#attributes'] = array('tabindex' => '5');К сожалению, при изменении tabindex почему-то перестал работать BUEditor (кнопочки сверху поля), поэтому я прибегнул все-таки к первому способу. А вы уже выбирайте по ситуации ;)
Это просто праздник! Спасибо огромное. Буду пробовать.
А еще уроки будут?
да, симпатично, но юзабельнее ли?
исходный вариант, как минимум, обычнее/привычнее
# | antoha
"Любую форму в пятой версии Друпала можно темизировать создав в файле шаблона template.php "
Под шестеркой производил кто-нибудь эти манипуляции?
# | Роман
В друпал 6 добавьте функцию (вместо andreas02 название вашей темы)
function andreas02_theme() {
return array(
// The form ID.
'comment_form' => array(
// Forms always take the form argument.
'arguments' => array('form' => NULL),
),
);# | Михаил
Это больше чем о форме комментирования. Здесь затронуто несколько вещей, которые я не мог понять даже прочитав книгу.
Ваше объяснение куда лучше и внятнее. Огромное спасибо.
Согласен что форма выглядит чище без лишних наворотов. Вопрос такой, а где взять/купить такую же форму?
# | Юрий
Как убрать поле "ТЕМА" ? Что бы не создавались нелепые огрызки от первых слов комментария в качестве темы?
# | Dmitry
В папкой с темой откройте файл comment.tpl.php и удалите <?php print $title ?>
# | Александр
откуда у вас модуль ajax_comment? пожалуйста поделитесь с сообществом. искал его на drupal.org - и все что нашел - ajax_comment.txt.tar модуль ajax_comment 5.x-0.0dev - версия никакая, ну а в списке проектов друпала такого модуля и подавно нет. Ведь модуль то существует, почему его нигде нет? или я не там искал...
Единственной причиной почему на д.орге еще не сделали нормальной реализации данного модуля, является невозможность "врезаться" в нужный функционал комментов без патчей ядра. Исходя из этого, автору [мне] не хочется отгрести задач по поддержке. Поэтому модуль остается в личной коллекции, а также идет в бонус сайтам моего производства. Может быть модуль появится на публике позже, и, возможно, не на лицензии GPL, хотя, все может быть.
# | заинтересованный
Однако, очень хотелось бы его видеть в каком-либо варианте для личных нужд ;)
# | Александр
Спасибо за подробный ответ! Жаль! ну значит будем пробовать написать свой модуль ajax_comment ;-) и спотыкаться о всем (кто разрабатывал подобный модуль) известные грабли.. как только изобретем - можно будет (если есть желание) сравнить и улучшить оба "велосипеда".
# | kleale
Спасибо. отличная статья. Только вот вижу у Вас на сайте сейчас другая форма комментариев)))
Подскажите как сделать выпадающую форму комментариев при нажатии на ссылку ответить под комментом пользователя - как у вас сделано.
И еще маленький вопрос, если не трудно - подскажите как добавить такой прикольный фейдинг эффект к просмотру комментария.
И еще у меня на сайте почему-то комментарий после отправки через аякс не показывается на странице - нужно обязательно обновить.
Использую последнюю версию jstools и ajaxsubmit
На счет формы, вы малехо опоздали, эта форма с предыдущего редизайна. Сейчас хоть и выглядит она по-другому, но подход тот же. По поводу аякс-коментов, см. выше, я уже рассказал все товарищу Александру. К сожалению, до теперь ситуация не изменилась.
По эффектам — JQuery.animate(), обучающий скринкаст, сайт с мануалом вам в помощь. Пока сами не разберетесь, боюсь, ничего не выйдет.
© And May The Force Be With You, Young Jedi
# | kleale
Спасибо за оперативный ответ :D
Но все таки хоть чуть-чуть подскажите как сделать появляющуюся форму комментариев при нажатии ссылки "ответить". Дайте подсказку где копать.
# | Vladimir
Подскажите, если не затруднит, как сделать возможность получать комментарии на емайл? (у вас, -- галочка под полем комментария), для этого используется Actions.module, или это возможно сделать стандартными средствами Drupala?
# | Roma
кто-нить может сказать как сделать точно такую форму для коментариев как здесь, можно без выпадания, но чтобы точно такие же поля, модуль есть?
Или прописывать стандартные хтмл формы...?
Роман, нет такого модуля в открутом доступе. Вы можете сделать все руками или заплатить за работу программисту.
# | Серго
А вообще есть модуль комментария, где есть поля Имя, почта, сайт???
У меня версия друпала 5.12.
Не могу найти что-то
Приветствую!
не хочу показаться неумным, но все-же спрошу:
каким образом вы изменили внешний вид формы ? не могу пока понять :(
Вероятно, прочитав статью и использовав эту информацию? :)
Есть вариант, что вы не догадались открыть зиппер и не увидили статьи как таковой. Нужно что-то с ним делать, он многих сбивает с толку.
# | dmitry
Прошу прощения за поистине "глупый" вопрос: ...а где собственно сама статья?
посыпаю голову пеплом.... чувствую что я что-то упустил :)
однако при запрещенном JS зиппер не открывается.
Попытался очеловечить свою форму комментирования, но ничего не выходит...
Вот что находится в template.php:
<?php
/**
* Implementation of theme_filter_tips_more_info().
* Used here to hide the "More information about formatting options" link.
*/
function phptemplate_filter_tips_more_info() {
return '';
}
/**
* Return a themed breadcrumb trail.
*
* @param $breadcrumb
* An array containing the breadcrumb links.
* @return a string containing the breadcrumb output.
*/
function phptemplate_breadcrumb($breadcrumb) {
if (!empty($breadcrumb)) {
return '<div class="breadcrumb">'. implode(' › ', $breadcrumb) .'</div>';
}
}
function phptemplate_comment_form($form) {
// Тут код из статьи, вырезал для экономии пространства.
return $output;
}
function blackparksnow_theme() {
return array(
'comment_form' => array(
'arguments' => array('form' => NULL),
),
);
}
Инфо-файл называется blackparksnow.info
Однако функция blackparksnow_theme() вызывается только на странице управления стилями при сохранении, какой стиль будет выбран по умолчанию. Соответственно, форма комментирования остается в первозданном виде.
Что здесь не так?
Друпал 6.8
Немогу добиться даже чтобы пропадали формы комментирования :(
последняя версия того, что я вставлял в template.php
function garland_theme() {
return array(
'comment_form' => array(
'arguments' => array('form' => NULL),
),
);
}
function garland_comment_form($form) {
$output = '';
return $output;
}в чём ошибка?
сегодня в 03:11 - возможно на сервере время неправильное... у меня на часах пятый час О:-)
Спасибо разобрался. В верхнем варианте всётаки какая-то ошибка. Правильный вариант для гарланда друпал6.* (может кому пригодится):
function garland_theme() {
return array(
'comment_form' => array(
'arguments' => array('form' => NULL),
),
);
}
function garland_comment_form($form) {
// всякий разный текст
//выводим форму
$output .= drupal_render($form);
return $output;
}
Сижу ковыряю дальше. В связи с этим вопрос:
Моли в $form['homepage']['#value'] = '';
Вставить что-то типа value="E-mail" onblur="if(this.value=='') this.value='E-mail';" onfocus="if(this.value=='E-mail') this.value='';" ?
Никак не могу разобраться с синтаксисом :(
$form['mail']['#attributes'] = array(
'onblur' => '...',
'onfocus' => '...',
);
А вообще, такое делается плагином джейквери. К сожалению забыл название, но если захотеть, очень легко найти. И второе, даже если делать без плагина, то такой код лучше уж выносить в отдельный js файл, цеплять его прямо в form_alter через drupal_add_js(), а в файле будет примерно следущее:
$(document).ready(function(){
$('#comment-form #edit-mail').blur(function(){
if ($(this).val() == '') {
$(this).val(Drupal.t('E-mail'));
}
});
$('#comment-form #edit-mail').focus(function(){
if ($(this).val() == Drupal.t('E-mail')) {
$(this).val('');
}
});
});Можно такой код лепить еще и в суффикс элемента.
Не понял зачем нужны оборачивания в лишний див для name, mail и поля коментария. До их свойств можно добраться в CSS так:
form#comment-form div#edit-name-wrapper {}
form#comment-form div#edit-mail-wrapper {}
form#comment-form div#edit-homepage-wrapper {}
form#comment-form div#edit-comment-wrapper {}Но штука с префиксами и суффиксами очень полезная. себе сделал:
// Вставляем див перед формой ввода, чтобы она никуда не плавала
$form['comment_filter']['comment']['#prefix'] = '<div class="clear-block"></div>';
потому, что оно оборачивает и .form-item дивы, к которым невозможно достучаться по-другому
Возможно код в 5.* и 6.* разный..
у меня в шестом на выходе код:
<form action="/comment/reply/22" accept-charset="UTF-8" method="post" id="comment-form">
<div> //наверно лишнее обёртывание всего, что в form'e, но хз как убрать
<div class="form-item" id="edit-mail-wrapper">
<label for="edit-mail">E-mail: <span class="form-required" title="Обязательное поле">*</span></label>
<input type="text" maxlength="64" name="mail" id="edit-mail" size="20" value="" class="form-text required" />
</div>
... другие разные дивы с формами
через CSS обращение:
весь див - form#comment-form div#edit-mail-wrapper {}
лейбл внутри - form#comment-form div#edit-mail-wrapper label{}
инпут - form#comment-form div#edit-mail-wrapper input{}
можно и без "form#comment-form"наверно, посто боюсь в другом месте задеть что-нибудь
Да, в шестерке они появились, но в пятке еще не было. Статья была написана изначально для пятерки ;)
ЗЫ. А див внутри формы не лишний. W3C так постановило.
# | анонимус
как сделать вывод формы комментария и список комментов на ноду
на отдельной странице или в отдельном табе в на той же странице.
есть идеи?
Привет! Отличная статья, много комментариев и вроде все понятно, но почему то на шестерке так и не заработало - формы какими были, такими и остались. РЕдактировал изначально тему bluemarine, переименовав ее, поменяв заобно параметр name в инфо файле. Функцию, как Вы писали, добавил, и вторую тоже. Смущает то, что изначально файла template.php не было, я взял его из темы garland, удалил оттуда все функции кроме функции для breadcrumb(пригодится). Может, в этом дело?
стыдно признаться, не нашел где это, да и почему то думал, что имели ввиду кэш браузера:) простите нуба:)
но я нашел где это! Спасибо! вот же странно, а вроде кэширование стоит отключенное, а все равно помогло...
да, ладно, не стоит :)
Это почти что два самых частых заблуждения о кеше — что имеется в виду кеш бразуера, и что отключенный кеш контента как-то влияет на кеш темизации и меню.
# | vadbars
Много вопросов по "зиппер". :) Красиво, прикольно, но не юзабельно.
Может быть, просто стоит перед ним написать пару слов типа "Откройте молнию" или "Расстегните и увидите"?
# | Boastman
Приветствую. У меня Drupal 6 и тема, которая является подтемой темы Zen.
Вот как выглядит код функции <имя темы>_theme:
function zensubtheme_theme(&$existing, $type, $theme, $path) {
$hooks = zen_theme($existing, $type, $theme, $path);
// Add your theme hooks like this:
/*
$hooks['hook_name_here'] = array( // Details go here );
*/
// @TODO: Needs detailed comments. Patches welcome!
return $hooks;
}Подскажите, пожалуйста, как мне ее модифицировать, чтобы задействовать
return array(
'comment_form' => array(
'arguments' => array('form' => NULL),
),
);
Щас тоже начал комментарии переделывать. По умолчанию нечто мрачное устанавливается. Одно "Ваше имя: такое-то" для залогиненного пользователя чего стоит. В 6-й версии похоже убирается полностью так:
// убираем имя автора (если юзер залогинен)
if ($form['_author'])
unset($form['_author']['#type']);
unset($form['_author']['#value']);# | ChemAli
Наконец-то мне это понадобилось :)
Лучше сначала объявить названиетемы_theme(), потомучто без нее phptemplate_comment_form() не отрабатывает
Еще я предварительно переопределил phptemplate_username() и выводилось имя пользователя, несмотря на unset, поэтому я полностью удалил автора: unset($form['_author']);
Еще раз спасибо!
Ссылки с других сайтов
Все молчат как партизаны.