Обработка голосований

Набросал прототип кода для обработки голосований в движке. Это не законченный код, а некий его прототип, может кому пригодиться, пока не вышла новая версия. Этот код позволяет легко управлять голосованием и снизить объём HTML кода.

JS класс на Mootools:
<script>
var msgErrorBox=new Roar({
			position: 'upperRight',
			className: 'roar-error'
		});	
var msgNoticeBox=new Roar({
			position: 'upperRight',
			className: 'roar-notice'
		});

var DIR_WEB_ROOT='http://livestreet';
var lsVote;


var lsVoteClass = new Class({
					   
	Implements: Options,

	options: {
		classes_action: {
			voted: 		'voted',			
			plus:  		'plus', 
			minus: 		'minus',
			positive: 	'positive',
			negative: 	'negative',
			quest: 		'quest'
		},
		classes_element: {
			voting: 	'voting',
			count:  	'count',			
			total:  	'total',			
			plus:  		'plus',	
			minus:  	'minus'	
		}		
	},
	
	typeVote: {
		topic_comment: {
			url: DIR_WEB_ROOT+'/include/ajax/voteComment.php'
		}
	},

	initialize: function(options){		
		this.setOptions(options);			
	},
	
	vote: function(idTarget,objVote,value,type) {		
		if (!this.typeVote[type]) {
			return false;
		}
		
		this.idTarget=idTarget;
		this.objVote=objVote;
		this.value=value;
		this.type=type;		
		thisObj=this;
		
		JsHttpRequest.query(
  			this.typeVote[type].url,
  			{ idComment: idTarget, value: value },
  			function(result, errors) {	
  				thisObj.onVote(result, errors, thisObj);  				
			},
  			true
		);		
	},
	
	onVote: function(result, errors, thisObj) {		
     	if (!result) {
     		msgErrorBox.alert('Error','Please try again later');		
     	}     	
     	if (result.bStateError) {
     		msgErrorBox.alert(result.sMsgTitle,result.sMsg);
     	} else {
     		msgNoticeBox.alert(result.sMsgTitle,result.sMsg);
     		
     		var divVoting=thisObj.objVote.getParent('div.'+thisObj.options.classes_element.voting);
     		divVoting.addClass(thisObj.options.classes_action.voted);
     		
     		if (this.value>0) {
     			divVoting.addClass(thisObj.options.classes_action.plus);
     		} 
     		if(this.value<0) {
     			divVoting.addClass(thisObj.options.classes_action.minus);
     		}     		
     		
     		var divTotal=divVoting.getChildren('div.'+thisObj.options.classes_element.total);     		
     		result.iRating=parseInt(result.iRating);     		
     		if (result.iRating>0) {
     			divVoting.removeClass(thisObj.options.classes_action.negative);
     			divVoting.addClass(thisObj.options.classes_action.positive);
     			divTotal.set('text','+'+result.iRating);
     		}
     		if (result.iRating<0) {
     			divVoting.removeClass(thisObj.options.classes_action.positive);
     			divVoting.addClass(thisObj.options.classes_action.negative);
     			divTotal.set('text',result.iRating);
     		}
     		if (result.iRating==0) {
     			divTotal.set('text','0');
     		}
     	}     	
	}
	
});

window.addEvent('domready', function() {  	
      lsVote=new lsVoteClass();
});
</script>


Стили:
.voting a{
	width:14px; 
	height:13px;
	display:block;
}

.voting.voted .plus a, .voting.voted .minus a, .voting.quest .plus a, .voting.quest .minus a {
	cursor:default;
}

.voting.plus .plus a {
	background:transparent url(templates/skin/habra/img/vote_comment_up.gif) no-repeat;
}

.voting.plus .minus a {
	background:transparent url(templates/skin/habra/img/vote_comment_down_gray.gif) no-repeat;
}

.voting.minus .plus a {
	background:transparent url(templates/skin/habra/img/vote_comment_up_gray.gif) no-repeat;
}

.voting.minus .minus a {
	background:transparent url(templates/skin/habra/img/vote_comment_down.gif) no-repeat;
}

.voting .minus a{		
	background:transparent url(templates/skin/habra/img/vote_comment_down.gif) no-repeat;	
}

.voting .plus a{	
	background:transparent url(templates/skin/habra/img/vote_comment_up.gif) no-repeat;
}

.voting.quest .minus a {
	background:transparent url(templates/skin/habra/img/vote_comment_down_gray.gif) no-repeat;
}

.voting.quest .plus a {
	background:transparent url(templates/skin/habra/img/vote_comment_up_gray.gif) no-repeat;


}

.voting .total{
	color: #c5c5c5;
}

.voting.negative .total{
	color: #ff0000;
}

.voting.positive .total{
	color: #339900;
}


HTML голосования:
<div class="voting">
	<div class="count">12</div>
	<div class="total">0</div>
	<div class="plus"><a href="#" onclick="lsVote.vote(117,this,1,'topic_comment'); return false;"></a></div>
	<div class="minus"><a href="#" onclick="lsVote.vote(117,this,-1,'topic_comment'); return false;"></a></div>
</div>


И не забываем подключить либы:
<script type="text/javascript" src="http://livestreet/classes/lib/external/MooTools_1.2/mootools-1.2-core-yc.js"></script>
<script type="text/javascript" src="http://livestreet/classes/lib/external/JsHttpRequest/JsHttpRequest.js"></script>
<script type="text/javascript" src="http://livestreet/classes/lib/external/MooTools_1.2/plugs/Roal/Roar.js"></script>

49 комментариев

avatar
спасибо, потестируем. Будем ждать финал релиз данной оптимизации, так как она действительно очень нужна!
avatar

Макс, обьясни, что это у тебя в HTML голосования:
<div class="voting">
        <div class="count">12</div>
        <div class="total">0</div>
        <div class="plus"><a href="#" onclick="lsVote.vote(117,this,1,'topic_comment'); return false;"></a></div>
        <div class="minus"><a href="#" onclick="lsVote.vote(117,this,-1,'topic_comment'); return false;"></a></div>
</div>

count — рейтинг комментария?
total — кол-во проголосовавших за комментарий?
117 — id комментрия?
avatar
count — количество проголосовавших, пока не выводится никак
total — рейтинг
117 — id коммента
avatar
кнопки не показывает, видать какая-то ошибка в CSS
avatar
поправь пути к картинкам в CSS
avatar
проверяла :) я бы так просто не писала бы :)
avatar

там css не совсем правильный по-моему .voting.minus .minus ;)
avatar
это я к тому, что нужно поправить. там много такого ) Вообще я сейчас попробую переписать с использованием css sprites
avatar
со спрайтами там только в бэкграунд смещения добавить
avatar
ошибки нет, так надо :)
avatar
посмотри через инспектор FireBug'а
avatar

DIR_WEB_ROOT по-моему определяется в header.tpl. Нужно только перенести его выше подключения этого скрипта.

насколько я понял сейчас реализованно только голосование за комментарии, правильно?typeVote: {
                topic_comment: {
                        url: DIR_WEB_ROOT+'/include/ajax/voteComment.php'
                }
        },
  • skif
  • +1
avatar
да, можно по аналогии добавить остальные типы.
но здесь нужно изменить обработчики аякса, т.к. сейчас они принимают на вход разные параметры(idComment, idTopic и т.п.), сделать их, например, idTarget
avatar
либо к параметру URL добавить еще один — nameTarget, и его передавать
avatar
а это самое насущное, я, например, отключил голосование за комменты у себя, потому что они в 1.5 увеличивали весь страницы… что без постраничности у пользователей такую бурю негодования подняли… жесть :)
avatar
здесь msgErrorBox, msgNoticeBox и DIR_WEB_ROOT определены только по одной причине — я тестировал всё это не в шаблонах, а просто создал файлик livestreet/test.php и на нём проверял
avatar

if (result.bStateError) {
                msgErrorBox.alert(result.sMsgTitle,result.sMsgTitle.sMsg);
        } else {
                msgNoticeBox.alert(result.sMsgTitle,result.sMsgTitle.sMsg);
нужно исправить на
if (result.bStateError) {
                msgErrorBox.alert(result.sMsgTitle,result.sMsg);
        } else {
                msgNoticeBox.alert(result.sMsgTitle,result.sMsg);
  • skif
  • +1
avatar
спасиб, исправил
avatar

я переделал часть, касающуюся css

/* css voter */

.voting a.btn {
        width:14px;
        height:13px;
        display:block;
                background: transparent url(../img/btnVoteComment.png) no-repeat;
                outline: 0;
}
/* can vote*/
.voting a.minus {
        background-position: top right;
}
.voting a.plus {
        background-position: top left;
}

.voting a.minus:hover {
        background-position: -14px -13px;
}
.voting a.plus:hover {
        background-position: 0-13px;
}
/* can vote*/

.voting.voted a.minus {
        background-position: bottom right;
}

.voting.voted a.plus {
        background-position: bottom left;
}
/* voted */

.voting.negative a.minus {
        background-position: top right !important;     
}

.voting.positive a.plus {
        background-position: top left !important;      
}
/**/
.voting .total{
        color: #c5c5c5;
}

.voting.negative .total{
        color: #ff0000;
}

.voting.positive .total{
        color: #339900;
}

html

<!-- -->
<div class="voting">
        <div class="count">0</div>
        <div class="total">{$oComment->getRating()}</div>
        <div><a class="btn plus" href="#" onclick="lsVote.vote({$oComment->getId()},this,1,'topic_comment'); return false;"></a></div>
        <div><a class="btn minus" href="#" onclick="lsVote.vote({$oComment->getId()},this,-1,'topic_comment'); return false;"></a></div>
</div>
<!-- -->
 

картинка btnVoteComment.png
  • skif
  • +2
avatar
тоже черновой вариант, но без повторений background: url() и с hover-эффектом для кнопочек ;)
  • skif
  • +1
avatar
а куда сам js код подключать?
avatar

я в main.js подключил в конце… только в header.tpl вот эту конструкцию нужно выше подключения самого main.js перенести
<script type="text/javascript">
var DIR_WEB_ROOT='{$DIR_WEB_ROOT}';
var DIR_STATIC_SKIN='{$DIR_STATIC_SKIN}';
var BLOG_USE_TINYMCE='{$BLOG_USE_TINYMCE}';
</script>

ну и это убрать
<script>
var msgErrorBox=new Roar({
                        position: 'upperRight',
                        className: 'roar-error'
                });    
var msgNoticeBox=new Roar({
                        position: 'upperRight',
                        className: 'roar-notice'
                });

var DIR_WEB_ROOT='http://livestreet';
avatar
тут есть маленький недостаток, число нельзя расположить между кнопок -Х 1 +Х
avatar
почему нельзя? Через стили можно как угодно расположить
avatar
про аноним нот войтинг забыли? :)
avatar

к предыдущемы… замена в actions/actionBlog/comment.tpl
<!-- -->
{if !$oComment->getDelete()}

{if $oUserCurrent}  
    {if $oComment->getUserId()==$oUserCurrent->getId()}
                <div class="voting voted">
        {else} 
        {if $oComment->getUserIsVote()}        
                        {if $oComment->getUserVoteDelta()>0}
                                <div class="voting positive">
                        {else}
                                <div class="voting voted negative">
                    {/if}
                {else}         
                        <div class="voting">
                {/if}
    {/if}
{else}
        <div class="voting voted">
{/if}
        <div class="count"></div>
        <div class="total">{$oComment->getRating()}</div>
        <div><a class="btn plus" href="#" onclick="lsVote.vote({$oComment->getId()},this,1,'topic_comment'); return false;"></a></div>
        <div><a class="btn minus" href="#" onclick="lsVote.vote({$oComment->getId()},this,-1,'topic_comment'); return false;"></a></div>
</div>

{/if}
<!-- -->

и в мой css добавить вверх
.voting {
        float:right;
        height:13px;
}

.voting div {
        float:left;
        padding: 0002px;
}

у меня все работает ;) спасибо ort`у. Давно ждал…
  • skif
  • +1
avatar
число ниже кнопочек немножко, каким образом чуть поднять можно?
avatar

.voting .total{
        margin:-10px 000;
}
ну -10 многовато конечно, это так, для примера. В реальности хватит и -1
avatar

<div class="voting voted">
во втором вхождении лучше заменить на
<div class="voting quest">
avatar
хотя ты его из CSS убрал
avatar
юзер 1 и юзер2
юзер два проголосовал положительно — всё отлично зеленая кнопка активна, красная неактивна
юзер2 проголосовал отрицательно красная активна, зеленая не активна, по после рефреша активны обе
заходим юзером 1 на сайт и видим свои оценки напротив комментариев серым цветом как положительные так и отрицательные
avatar

а какой код в шаблоне /actions/actionBlog/comment.tpl? После рефреша ну никак не могут быть активны обе кнопки… потому как{if $oComment->getUserVoteDelta()>0}
                                <div class="voting positive">
                        {else}
                                <div class="voting voted negative">
                    {/if}т.е. либо то, либо другое.

Насчет серого цвета — пока не занимался
avatar
странно теперь если положительно проголосовать!
avatar
еще посмотрите результат общей работы в ИЕ6 :(
avatar
так я ж говорю черновой вариант… нужно дорабатывать. Выложил просто потому, что может кому пригодится или просто интересно.
avatar

вот небольшая поправочка. цифорка меняет цвет (зеленая/красная) и при перезагрузке страницы нормально отображается результат голосования.<!-- -->
{if !$oComment->getDelete()}

{if $oUserCurrent}  
    {if $oComment->getUserId()==$oUserCurrent->getId()}
                <div class="voting voted">
        {else} 
        {if $oComment->getUserIsVote()}        
                        {if $oComment->getUserVoteDelta()>0}
                                <div class="voting voted positive">
                        {else}
                                <div class="voting voted negative">
                    {/if}
                {else}         
                        {if $oComment->getRating()>=0}
                                <div class="voting positive">
                        {else}
                                <div class="voting negative">
                        {/if}
                {/if}
    {/if}
{else}
        <div class="voting voted">
{/if}
        <div class="count"></div>
        <div class="total">{$oComment->getRating()}</div>
        <div><a class="btn plus" href="#" onclick="lsVote.vote({$oComment->getId()},this,1,'topic_comment'); return false;"></a></div>
        <div><a class="btn minus" href="#" onclick="lsVote.vote({$oComment->getId()},this,-1,'topic_comment'); return false;"></a></div>
</div>

{/if}
<!-- -->
avatar
сейчас при голосовании отрицательно показывает так: --1
после рефреша всё нормально -1
если зайти автором, которому ставили оценки все циферки серенькие
avatar

В js коде замени
divTotal.set('text','-'+result.iRating);
на
divTotal.set('text',result.iRating);
avatar
не спасает, пробовала, до того как написать
avatar
у тебя всегда так :)
от двойного минуса это спасет точно
avatar
вот исправленный код, чтобы и у автора были оценки цветные paste.org.ru/?yb5mxb
avatar
ой нет… не то ))
avatar
avatar
только не бейте :) у автора комментов кнопки не серые :)
avatar
а можно исходный код глянуть, в том месте где «не серые»?
avatar
paste.org.ru/?2j6f81
вот код comment.tpl
сейчас ниодна кнопка не нажимается
avatar
да и сейчас при нажатии на кнопочки никаких действий не происходит: Р
avatar
ничего себе пригодиться, эта проблема еще с первых версий ЛС
avatar
ну на чем остановились то? У Макса в теле топика рабочий код теперь или бета версия? :))
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.