Система рейтинга

Материал из Umicms
Версия от 11:49, 5 июня 2013; Mad grant (обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к:навигация, поиск

Реализовано в продукте версии 2.9

Задача:

Организовать систему рейтинга для объектов UMI.CMS.

Решение:

Организуем рейтинг с использованием jQuery и Ajax на примере объектов каталога. В начале, необходимо отредактировать тип данных "Объект каталога": зайдите в модуль "Шаблоны данных", найдите тип данных "Объект каталога" и откройте его для редактирования. Нажмите кнопку "Добавить группу" и задайте имя группы, например - "Рейтинг". В созданной группе добавьте два поля типа "Число":

  • "Хороший" (good);
  • "Плохой" (bad).

Rate fields.png

Группа полей "Рейтинг"

Теперь необходимо написать макросы, которые будут работать с данными полями. Откройте файл "/classes/modules/vote/__custom.php" и добавьте код макросов сразу же после строки "//TODO: Write your macroses here".

Листинг 1. Код макросов установки и получения рейтинга

/*
  @title
    Установка рейтинга объекта
 */
public function setRate() {
  $id = (int)getRequest('id');
  if(!isset($id) || !is_numeric($id))
    throw new publicException('Invalid object ID');
    
  $type = (string)getRequest('type');
  if(!isset($type))
    throw new publicException('Invalid rate type');
    
  $hierarchy = umiHierarchy::getInstance();
  $element = $hierarchy->getElement($id);
  $rate = $element->getValue($type) + 1;
  $element->setValue($type, $rate);
  $element->commit();
  
  echo $rate;
}

/*
  @title
    Получение рейтинга объекта
  @param Integer
    $id - идентификатор объекта
  @param String
    $type - тип рейтинга (good/bad)
 */
public function getRate($id, $type) {
  if(!isset($id) || !is_numeric($id))
    throw new publicException('Invalid object ID');
    
  if(!isset($type))
    throw new publicException('Invalid rate type');
    
  $hierarchy = umiHierarchy::getInstance();
  $element = $hierarchy->getElement($id);
  $rate = $element->getValue($type);
  
  return (int)($rate ? $rate : 0);
}

После этого, нужно добавить разрешения для макросов. Создайте файл "/classes/modules/vote/permissions.custom.php" с таким содержимым:

Листинг 2. Разрешения для макросов

<?php
  $permissions = array(
    'post' => array('setRate', 'getRate')
  );
?>

Далее необходимо повесить обработчик на событие "click" для ссылок, которые будут устанавливать значение рейтинга. Для этого создайте файл "/js/rate.js" и напишите в него следующий код:

Листинг 3. Файл "rate.js"

jQuery(document).ready(function() {

  jQuery('.vote').click(function() {
    var cid = 'vote' + jQuery(this).attr('id');
    if(jQuery.cookie(cid)) {
      window.alert('Вы уже голосовали!');
      return false;
    }
    
    var self = jQuery(this);
    var parent = jQuery(this).parent();
    
    var id = jQuery(this).attr('id');
    var type = jQuery(this).attr('name');
    var req = 'id=' + id + '&type=' + type;
    var e = '.rate .' + type;
    
    parent.animate({'opacity': 0.3}, 200);
    jQuery.ajax({
      type: 'POST',
      url: '/udata/vote/setRate',
      data: req,
      cache: false,
    })
    .success(function(data) {
      self.html(data);
      parent.animate({'opacity': 1}, 200);
      jQuery.cookie(cid, 'true', {'expires': new Date().getTime() - 1});
    })
    .error(function() {
      window.alert('Ошибка! К сожалению, Ваш голос не будет учтён.');
      jQuery(e).animate({'opacity': 1}, 200);
    });
  });
  
  jQuery('.rate .good').hover(
    function() {
      jQuery(this).css('background-color', '#88D135');
    }, 
    function() {
      jQuery(this).css('background-color', '#4AA735');
    }
  );
  
  jQuery('.rate .bad').hover(
    function() {
      jQuery(this).css('background-color', '#FF7A32');
    }, 
    function() {
      jQuery(this).css('background-color', '#FF2926');
    }
  );
  
});

Событие "click" будет обрабатываться у ссылок с классом "vote". Также в данном коде присутствует обработчики события "hover". Он срабатывает при наведении курсора мыши и меняет цвет кнопки рейтинга. По желанию, этот функционал можно удалить.

Осталось задать стиль панели рейтинга. Создайте файл "/css/rate.css" со следующим содержимым:

Листинг 4. Файл "rate.css"

.rate,
.good,
.bad
{
  float: left;
}

.rate span
{
  float: left;
  margin: 2px 12px 4px 20px;
  color: #4A89BA;
  font-size: 12px;
  font-weight: bold;
}

.good,
.bad
{
  padding: 4px 12px;
  text-align: center;
  margin: 0 2px;
  border-radius: 5px;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
}

.good a,
.bad a
{
  color: #000;
  font-weight: bold;
  font-size: 15px;
  text-decoration: none;
}

.good
{
  background-color: #4AA735;
}

.bad
{
  background-color: #FF2926;
}

Для примера, подключим панель рейтинга в стандартный XSLT-шаблон UMI.CMS "Интернер-магазин современный" (DemoDizzi). Откройте файл "/xsltTpls/layouts/default.xsl" и подключите созданные файлы "rate.js" и "rate.css" в секции "head" следующим образом:

Листинг 5. Подключение файлов "rate.js" и "rate.css"

<!-- Рейтинг -->
<script type="text/javascript" src="/js/rate.js"></script>
<link rel="stylesheet" type="text/css" href="/css/rate.css" />

После того, как файлы будут подключены, останется отредактировать шаблон вывода информации об объекте каталога. Откройте файл "/xsltTpls/modules/catalog/object-view.xsl" и разместите следующий код после блока "price", чтобы получилось примерно так:

Листинг 6. Размещение панели рейтинга в шаблоне

<!-- Блок "price" -->
<div class="price">
  <span umi:element-id="{page/@id}" umi:field-name="price">
    <xsl:apply-templates select="document(concat('udata://emarket/price/', page/@id))" />
  </span>
</div>

<!-- Панель рейтинга -->
<div class="rate">
  <div class="good">
    <a class="vote" id="{page/@id}" name="good" title="Хороший" href="javascript: void(0);">
      <xsl:value-of select="document(concat('udata://vote/getRate/', page/@id, '/good/'))/udata" />
    </a>
  </div>
  <div class="bad">
    <a class="vote" id="{page/@id}" name="bad" title="Плохой" href="javascript: void(0);">
      <xsl:value-of select="document(concat('udata://vote/getRate/', page/@id, '/bad/'))/udata" />
    </a>
  </div>
</div>

Rate-panel.png

Панель рейтинга

Важно.

Для работы представленной системы рейтинга в шаблон должны быть подключены библиотека jQuery и плагин jQuery Cookie. Если в шаблоне вызывается макрос includeQuickEditJs, то jQuery и jQuery Cookie подключатся автоматически.

Примечание.

Данный функционал был проверен на работоспособность в версии системы 2.8.5.1.