FiveStar Rating. Ещё одно решение...

Главные вкладки

Аватар пользователя beliy_snow beliy_snow 3 апреля 2007 в 10:49

Итак. Сегодня делаем голосование с помощью звездачек. На эту тему писано-переписано, не я первый, не я последний. Окончательное решение всегда остается за вами. Если вас не устраивает то, что в каком-то модуле подключается AJAX, или ещё что-то не устраивает - тут будет решение работающее только на JavaScript. Даже стилей не надо никаких добавлять. Только звездочки нарисуйте 2 штуки и нормально. Поехали.

Для начала надо пояснить что нам понадобится кроме ЯваСкрипта и звездочек. Нам понадобится собственно модуль, который позволяет нам делать голосование - votingapi. Скачали, установили, без трудностей. Теперь у нас есть API для работы с голосованием. Именно сейчас писать как я прикручивал голосование в комментарии я не буду (т.е. вызовы API-шных функций, засовывание результатов в базу, PRE и POST валидация). Напишу лучше просто как в форму комментария засунуть обычное голосование с помощью Radio-buttons, которое мы собственно потом заменим на звездочки.

Меняем форму коментария.
Наверняка у вас есть свой сайт, куда вы прикручиваете новые модули, изменяете функционал, просто извращаетесь в конце концов. Если вас все устраивает - хорошо, но я бы рекомендовал вам завести отдельный модуль для всех своих действий и назвать его именем своего сайта. Это для удобства. Чтобы если что-то не так - отключили модуль и сайт снова жив, пусть и без какого-то функционала. И ещё ведь гораздо удобнее менять все в одном месте, чем лазить по нативным модулям в тысячах строках кода. Лирическое отступление закончилось. Началась практика. Нам надо обработать форму комента, обрабатываем в файле вашего модуля.
function ваш_модуль_form_alter($form_id, &$form) {
global $user;
if('comment_form' == $form_id) {
$node = node_load(array('nid' => $form['#parameters'][1]['nid']));
if ($user->uid != $node->uid)
{
drupal_add_js(path_to_theme() . '/script/fivestar.js');
$inserted_vobj = votingapi_get_vote('comment', $form['#parameters'][1]['cid'], COMMENT_VOTINGAPI_VALUE_TYPE, 'comment:article', $form['#parameters'][1]['uid']);
$disabled = ($inserted_vobj->value) ? TRUE : FALSE;
$form['vote_value'] = array(
'#type' => 'radios',
'#disabled' => $disabled,
'#title' => t('Your vote'),
'#description' => t('Select a value from 1 (worst) to 5 (best)'),
'#default_value' => ($inserted_vobj->value) ? (string)$inserted_vobj->value : '1',
'#options' => array('1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4', '5'=>'5'),
'#required' => TRUE,
'#weight' => -1
);
$form['vote_tag'] = array('#type' => 'value', '#value' => 'comment:'.$node->type);
}
$form['#validate']['write_for_sp_form_validate'] = array();
}
}
?>
Все понятно? Smile Думаю, да. Разобраться тут вообще не сложно. Одно замечание - в моем проекте автор статьи не может ставить рейтинг к собственной статье, поэтому в форме добавления коментария автором статьи - звездочек не будет. Ещё мы подключили .js файл, где лежит наш ЯваСкрипт функционал.
Теперь у нас в форме комментария есть ещё одно поле, где мы выбираем рейтинг. Теперь нам надо заменить радио баттоны на картинки, сложного тут тоже ничего нет. Для этого нам надо переопределить вывод самих радиобаттонов и повесить на них ЯваСкриптовые обработчики. Делаем в файле шаблона вашей темы (template.php).
function ваша_тема_radio($element) {
_form_set_class($element, array('form-radio'));
$output = '';
if (!is_null($element['#title'])) {
$output = '' . $output . '';
}

unset($element['#title']);
return theme('form_element', $element, $output);
}
?>
Мы добавили id к нашим элементам, чтобы ЯваСкрипт мог их нормально находить с помощью функции getElementById(), так же повесили обработчики onmouseover, onmouseout и onclick. Зачем они нужны - понятно из названий. В них вызываются 3 наших ЯваСкриптовых функции, которые мы опишем дальше. (Сразу предупреждаю - в ЯваСкрипте я не мастер, так что сильно ногами не пинайте).
В папке с вашей темой создаем директорию script, туда кидаем файлик fivestar.js со следующим содержимым:
// функция смены картинки при наведении на звездочку
function change_star_state(star)
{
var elemRadio = document.getElementById('radio_' + star.name);
if (elemRadio.disabled != true)
{
for (i = 1; i < star.name; i++)
{
var elem = document.getElementById('star_' + i);
elem.src = "/где_лежит_ваша_тема/images/star_on.gif";
}
star.src = "/где_лежит_ваша_тема/images/star_on.gif";
}
}
// перестраиваем наши звездочки в зависимости от того, какой радиобаттон выбран
function clear_star_state()
{
for (i = 1; i < 6; i++)
{
var elemRadio = document.getElementById('radio_' + i);
var elemStar = document.getElementById('star_' + i);
if (elemRadio.checked == false)
{
elemStar.src = "/где_лежит_ваша_тема/images/star_on.gif";
}
else if (elemRadio.checked == true)
{
elemStar.src = "/где_лежит_ваша_тема/images/star_on.gif";
var checked = i+1;
break;
}
}
for (j = checked; j < 6; j++)
{
var elemStar = document.getElementById('star_' + j);
elemStar.src = "/где_лежит_ваша_тема/images/star_off.gif";
}
}
// чтобы знать какой рейтинг нам писать в базу - меняем состояние нажатого радиобаттона, пусть даже пользователю он не виден
function setChecked(star)
{
var elemRadio = document.getElementById('radio_1');
if (elemRadio.disabled != true)
{
for (i = 1; i < 6; i++)
{
var elemStar = document.getElementById('star_' + i);
elemStar.src = "/где_лежит_ваша_тема/images/star_off.gif";
}
var elem = document.getElementById('radio_' + star.name);
elem.checked = true;
change_star_state(star);
}
}
?>
Вот вроде бы и все... А, нет, не все. Помните строчку с '#default-value'? Там мы устанавливали значение по умолчанию в 1, т.е. должна быть выбрана первая звездочка. Чтобы звездочка была выбрана - нам при загрузке страницы необходимо вызвать яваскриптовую функцию clear_star_state(). Сделать это очень просто, зная как добавить переменные в шаблон, а именно переменную onload_atributes. Для этого снова идем в файл template.php и пишем простую функцию
function _phptemplate_variables($hook, $vars) {
switch($hook) {
case 'page' :
$vars['onload_atributes'] = 'clear_star_state();';
break;
}
return $vars;
}
?>
Теперь в любом из файлов .tpl.php нам доступна переменная $onload_atributes. Ну и ежу понятно, что без строчки

ничего работать не будет Smile

Картинки со звездочками тоже добавил, пользуйтесь.

ВложениеРазмер
Иконка изображения star_on.gif318 байт
Иконка изображения star_off.gif196 байт

Комментарии

Аватар пользователя kiev1 kiev1 25 апреля 2008 в 10:03

спасибо, это теперь понятно
непонятно другое - в этом модуле делаются поля CCK, то есть можно их сделать несколько, но как их вывести в ноду и что бы они считались отдельно - не понятно, подскажите пожалуйста.