1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-06-16 23:00:51 +03:00

Компонент poll

This commit is contained in:
Denis Shakhov 2014-06-23 19:51:40 +07:00
parent dedbae0f0c
commit 9a6f58b23b
25 changed files with 570 additions and 447 deletions

View file

@ -221,7 +221,7 @@ class ActionAjax extends Action {
if ($oVote->Add()) {
$oViewer=$this->Viewer_GetLocalViewer();
$oViewer->Assign('oPoll',$oPoll);
$this->Viewer_AssignAjax('sText',$oViewer->Fetch("polls/poll.result.tpl"));
$this->Viewer_AssignAjax('sText',$oViewer->Fetch("components/poll/poll.result.tpl"));
} else {
return $this->EventErrorDebug();
}
@ -245,7 +245,7 @@ class ActionAjax extends Action {
if ($oPoll->Add()) {
$oViewer=$this->Viewer_GetLocalViewer();
$oViewer->Assign('oPoll',$oPoll);
$this->Viewer_AssignAjax('sPollItem',$oViewer->Fetch("polls/poll.form.list.item.tpl"));
$this->Viewer_AssignAjax('sPollItem',$oViewer->Fetch("components/poll/poll.manage.item.tpl"));
return true;
} else {
$this->Message_AddError($this->Lang_Get('common.error.save'),$this->Lang_Get('error'));
@ -288,7 +288,7 @@ class ActionAjax extends Action {
if ($oPoll->Update()) {
$oViewer=$this->Viewer_GetLocalViewer();
$oViewer->Assign('oPoll',$oPoll);
$this->Viewer_AssignAjax('sPollItem',$oViewer->Fetch("polls/poll.form.list.item.tpl"));
$this->Viewer_AssignAjax('sPollItem',$oViewer->Fetch("components/poll/poll.manage.item.tpl"));
$this->Viewer_AssignAjax('iPollId',$oPoll->getId());
return true;
} else {

View file

@ -520,6 +520,7 @@ $config['head']['default']['js'] = array(
"___path.application.web___/frontend/common/js/talk.js",
"___path.application.web___/frontend/common/js/vote.js",
"___path.application.web___/frontend/common/js/poll.js",
"___path.application.web___/frontend/common/js/poll-manage.js",
"___path.application.web___/frontend/common/js/subscribe.js",
"___path.application.web___/frontend/common/js/geo.js",
"___path.application.web___/frontend/common/js/wall.js",

View file

@ -0,0 +1,257 @@
/**
* Управление опросами
*
* @module ls/poll-manage
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
(function($) {
"use strict";
$.widget( "livestreet.lsPollManage", {
/**
* Дефолтные опции
*/
options: {
// Ссылки
urls: {
// Мод. окно добавления опроса
modal_add: aRouter.ajax + 'poll/modal-create',
// Мод. окно редактирования опроса
modal_edit: aRouter.ajax + 'poll/modal-update',
// Добавление
add: aRouter.ajax + 'poll/create/',
// Редактирование
update: aRouter.ajax + 'poll/update/',
// Удаление
remove: aRouter.ajax + 'poll/remove/'
},
// Селекторы
selectors: {
// Список добавленных опросов
list: '.js-poll-manage-list',
// Опрос
item: '.js-poll-manage-item',
// Кнопка удаления опроса
item_remove: '.js-poll-manage-item-remove',
// Кнопка редактирования опроса
item_edit: '.js-poll-manage-item-edit',
// Кнопка добавления
add: '.js-poll-manage-add',
form: {
form: '#js-poll-form',
add: '.js-poll-form-answer-add',
list: '.js-poll-form-answer-list',
item: '.js-poll-form-answer-item',
item_id: '.js-poll-form-answer-item-id',
item_text: '.js-poll-form-answer-item-text',
item_remove: '.js-poll-form-answer-item-remove',
submit: '.js-poll-form-submit'
},
},
// Максимальное кол-во вариантов которое можно добавить в опрос
max: 20
},
/**
* Конструктор
*
* @constructor
* @private
*/
_create: function () {
var _this = this;
this.elements = {
list: this.element.find( this.options.selectors.list ),
add: this.element.find( this.options.selectors.add ),
remove: this.element.find( this.options.selectors.item_remove ),
edit: this.element.find( this.options.selectors.item_edit )
};
this.id = this.element.data('target-id');
this.type = this.element.data('type');
//
// События
//
// Показывает форму добавления
this._on( this.elements.add, { 'click': this.formShowAdd } );
// Показывает форму редактирования опроса
this.element.on( 'click' + this.eventNamespace, this.options.selectors.item_edit, function () {
_this.formShowEdit( $(this).data('poll-id'), $(this).data('poll-target-tmp') )
});
// Удаляет опрос
this.element.on( 'click' + this.eventNamespace, this.options.selectors.item_remove, function () {
_this.remove( $(this) )
});
},
/**
* Показывает форму
*
* @param {String} url Ссылка возвращающая модальное окно
* @param {Object} params Параметры
*/
formShow: function( url, params ) {
var _this = this;
ls.modal.load( url, params, {
aftershow: function ( e, modal ) {
var form = modal.element.find( _this.option( 'selectors.form.form' ) ),
list = form.find( _this.option( 'selectors.form.list' ) );
// Отправка формы
form.on( 'submit', function (e) {
_this[ form.data('action') ]( form, list, modal );
e.preventDefault();
});
// Добавление ответа
form.find( _this.option( 'selectors.form.add' ) ).on( 'click', _this.answerAdd.bind( _this, list ));
form.on( 'keydown', _this.option( 'selectors.form.item_text' ) , 'ctrl+return', _this.answerAdd.bind( _this, list ) );
// Удаление
form.on( 'click', _this.option( 'selectors.form.item_remove' ), function () {
_this.answerRemove( list, $( this ) );
});
},
center: false
});
},
/**
* Показывает форму добавления
*/
formShowAdd: function() {
this.formShow( this.option( 'urls.modal_add' ), { target_type: this.type, target_id: this.id } );
},
/**
* Показывает форму редактирования
*
* @param {Number} id ID опроса
* @param {String} hash Хэш опроса
*/
formShowEdit: function( id, hash ) {
this.formShow( this.option( 'urls.modal_edit' ), { id: id, target_tmp: hash } );
},
/**
* Добавляет вариант ответа
*
* @param {jQuery} list Список ответов
*/
answerAdd: function( list ) {
// Ограничиваем кол-во добавляемых ответов
if ( list.find( this.option( 'selectors.form.item' ) ).length == this.option( 'max' ) ) {
ls.msg.error( null, ls.lang.get( 'poll.notices.error_answers_max' ) );
return;
}
var item = $( this.option( 'selectors.form.item' ) + '[data-is-template=true]' ).clone().removeAttr( 'data-is-template' ).show();
list.append( item );
item.find( this.option( 'selectors.form.item_text' ) ).focus();
},
/**
* Удаляет вариант ответа
*
* @param {jQuery} list Список ответов
* @param {jQuery} button Кнопка удаления
*/
answerRemove: function( list, button ) {
if ( list.find( this.option( 'selectors.form.item' ) ).length == 1 ) {
// TODO: Fix text
ls.msg.error( null, ls.lang.get( 'poll.notices.error_answers_max' ) );
return;
}
button.closest( this.option( 'selectors.form.item' ) ).fadeOut(200, function () {
$(this).remove();
});
},
/**
* Проставляет индексы инпутам ответа
*
* @param {jQuery} list Список ответов
*/
answerIndex: function( list ) {
list.find( this.option( 'selectors.form.item' ) ).each(function ( index, item ) {
var item = $(item),
id = item.find( this.option( 'selectors.form.item_id' ) ),
text = item.find( this.option( 'selectors.form.item_text' ) );
id.attr( 'name', 'answers[' + index + '][id]' );
text.attr( 'name', 'answers[' + index + '][title]' );
}.bind(this));
},
/**
* Добавляет опрос
*
* @param {jQuery} form Форма
* @param {jQuery} list Список ответов
* @param {jQuery} modal Модальное окно с формой
*/
add: function( form, list, modal ) {
this.answerIndex( list );
ls.ajax.submit( this.option( 'urls.add' ), form, function( response ) {
this.elements.list.append( response.sPollItem );
modal.hide();
}.bind(this), { submitButton: modal.element.find( 'button[type=submit]' ) });
},
/**
* Обновление опроса
*
* @param {jQuery} form Форма
* @param {jQuery} list Список ответов
* @param {jQuery} modal Модальное окно с формой
*/
update: function( form, list, modal ) {
this.answerIndex( list );
ls.ajax.submit( this.option( 'urls.update' ), form, function( response ) {
this.elements.list.find( this.option( 'selectors.item' ) + '[data-poll-id=' + response.iPollId + ']' ).replaceWith( response.sPollItem );
modal.hide();
}.bind(this), { submitButton: modal.element.find( 'button[type=submit]' ) });
},
/**
* Удаляет опрос
*
* @param {jQuery} button Кнопка удаления
*/
remove: function( button ) {
ls.ajax.load( this.option( 'urls.remove' ), { id: button.data('poll-id'), tmp: button.data('poll-target-tmp') }, function ( response ) {
if (response.bStateError) {
ls.msg.error(null, response.sMsg);
} else {
button.closest( this.option( 'selectors.item' ) ).fadeOut('slow', function() {
$(this).remove();
});
}
}.bind(this));
},
});
})(jQuery);

View file

@ -1,283 +1,112 @@
/**
* Опросы
*
* Опрос
*
* @module ls/poll
*
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
var ls = ls || {};
(function($) {
"use strict";
ls.poll = (function ($) {
/**
* Дефолтные опции
*/
var defaults = {
// Роутеры
routers: {
vote: aRouter['ajax'] + 'poll/vote/',
add: aRouter['ajax'] + 'poll/create/',
update: aRouter['ajax'] + 'poll/update/',
remove: aRouter['ajax'] + 'poll/remove/'
},
// Селекторы
selectors: {
modal: '#modal-poll-create',
poll: {
poll: '.js-poll',
vote_form: '.js-poll-vote-form',
vote: '.js-poll-vote',
abstain: '.js-poll-abstain'
$.widget( "livestreet.lsPoll", {
/**
* Дефолтные опции
*/
options: {
// Ссылки
urls: {
// Голосование за вариант
vote: aRouter.ajax + 'poll/vote/'
},
form: {
form: '#js-poll-form',
list: '.js-poll-form-list',
item: '.js-poll-form-list-item',
item_remove: '.js-poll-form-list-item-remove',
submit: '.js-poll-form-submit'
},
// Селекторы
selectors: {
// Форма голосования
form: '.js-poll-vote-form',
answer: {
list: '.js-poll-form-answer-list',
add: '.js-poll-form-answer-add',
item: {
item: '.js-poll-form-answer-item',
text: '.js-poll-form-answer-item-text',
id: '.js-poll-form-answer-item-id',
remove: '.js-poll-form-answer-item-remove'
}
},
// Кнопка проголосовать
vote: '.js-poll-vote',
// Селекторы результата опроса
result: {
container: '.js-poll-result',
item: '.js-poll-result-item',
sort: '.js-poll-result-sort'
// Кнопка воздержаться от голосования
abstain: '.js-poll-abstain',
// Результата опроса
result: '.js-poll-result',
// Вариант
item: '.js-poll-result-item',
// Кнопка сортировки вариантов
sort: '.js-poll-result-sort'
}
},
// Максимальное кол-во вариантов ответов
iMaxAnswers: 20
};
/**
* Конструктор
*
* @constructor
* @private
*/
_create: function () {
var _this = this;
/**
* Инициализация
*
* @param {Object} options Опции
*/
this.init = function(options) {
var _this = this,
oDocument = $(document);
this.elements = {
form: this.element.find( this.options.selectors.form ),
vote: this.element.find( this.options.selectors.vote ),
abstain: this.element.find( this.options.selectors.abstain )
};
this.options = $.extend({}, defaults, options);
! this.elements.form.length && this.initResult();
//
// События
//
this._on( this.elements.vote, { 'click': this.vote.bind( this, false ) } );
this._on( this.elements.abstain, { 'click': this.vote.bind( this, true ) } );
this.element.on( 'click' + this.eventNamespace, this.option( 'selectors.sort' ), this.sort.bind(this) );
},
/**
* Форма добавления
* Иниц-ия результата
*/
// Сабмит формы
oDocument.on('submit', this.options.selectors.form.form, function (e) {
var oForm = $(this);
_this[ oForm.data('action') == 'add' ? 'add' : 'update' ](oForm, $(_this.options.selectors.form.submit));
e.preventDefault();
});
// Добавление варианта
oDocument.on('click', this.options.selectors.answer.add, function () {
_this.answerAdd($(_this.options.selectors.answer.list));
});
// Добавление варианта по нажатию Ctrl + Enter
oDocument.on('keyup', this.options.selectors.answer.text, function (e) {
var key = e.keyCode || e.which;
if (e.ctrlKey && key == 13) {
_this.answerAdd($(_this.options.selectors.answer.list));
}
});
// Удаление варианта
oDocument.on('click', this.options.selectors.answer.item.remove, function () {
_this.answerRemove($(this));
});
// Удаление опроса
oDocument.on('click', this.options.selectors.form.item_remove, function () {
var oButton = $(this),
oItem = oButton.closest(_this.options.selectors.form.item);
_this.remove(oItem.data('poll-id'), oItem.data('poll-target-tmp'));
});
initResult: function() {
this.elements.sort = this.element.find( this.options.selectors.sort );
this.elements.items = this.element.find( this.options.selectors.item );
this.elements.result = this.element.find( this.options.selectors.result );
},
/**
* Опрос
* Голосование
*/
vote: function( abstain ) {
ls.ajax.submit( this.option( 'urls.vote' ), this.elements.form, function( response ) {
this.element.html( $.trim( response.sText ) );
this.initResult();
$(this.options.selectors.poll.poll).each(function () {
var oPoll = $(this),
iPollId = oPoll.data('poll-id');
this._off( this.elements.vote, 'click' );
this._off( this.elements.abstain, 'click' );
}.bind(this), {
submitButton: this.elements.vote,
params: { abstain: abstain ? 1 : 0 }
});
},
// Голосование за вариант
oPoll.find(_this.options.selectors.poll.vote).on('click', function () {
var form = oPoll.find('form');
/**
* Сортировка результата
*/
sort: function() {
var type = this.elements.sort.hasClass( ls.options.classes.states.active ) ? 'position' : 'count';
_this.vote(form, $(this));
this.elements.items.sort( function (a, b) {
return $(b).data(type) - $(a).data(type);
});
// Воздержаться
oPoll.find(_this.options.selectors.poll.abstain).on('click', function () {
var form = oPoll.find('form');
_this.vote(form, $(this), true);
});
// Сортировка
oPoll.on('click', _this.options.selectors.result.sort, function () {
_this.toggleSort(oPoll);
});
});
};
/**
* Добавление опроса
*
* @param {Object} oForm Форма добавления опроса
* @param {Object} oButton Кнопка добавления
*/
this.add = function(oForm, oButton) {
this.answerIndex(oForm);
ls.ajax.submit(this.options.routers.add, oForm, function(oResponse) {
$(this.options.selectors.form.list).append(oResponse.sPollItem);
$(this.options.selectors.modal).modal('hide');
}.bind(this), { submitButton: oButton });
};
/**
* Обновление опроса
*
* @param {Object} oForm Форма добавления опроса
* @param {Object} oButton Кнопка сохранения
*/
this.update = function(oForm, oButton) {
this.answerIndex(oForm);
ls.ajax.submit(this.options.routers.update, oForm, function(oResponse) {
$(this.options.selectors.form.item + '[data-poll-id=' + oResponse.iPollId + ']').replaceWith(oResponse.sPollItem);
$(this.options.selectors.modal).modal('hide');
}.bind(this), { submitButton: oButton });
};
/**
* Удаление опроса
*
* @param {Number} iId ID ответа
* @param {String} sTempHash Хэш объекта
*/
this.remove = function(iId, sTempHash) {
ls.ajax.load(this.options.routers.remove, { id: iId, tmp: sTempHash }, function (oResponse) {
if (oResponse.bStateError) {
ls.msg.error(null, oResponse.sMsg);
} else {
$(this.options.selectors.form.item + '[data-poll-id=' + iId + ']').fadeOut('slow', function() {
$(this).remove();
});
}
}.bind(this));
};
/**
* Добавляет вариант ответа
*
* @param {Object} oAnswerList Блок с ответами
*/
this.answerAdd = function(oAnswerList) {
// Ограничиваем кол-во добавляемых ответов
if (oAnswerList.find(this.options.selectors.answer.item.item).length == this.options.iMaxAnswers) {
ls.msg.error(null, ls.lang.get('poll.notices.error_answers_max'));
return false;
this.elements.sort.toggleClass( ls.options.classes.states.active );
this.elements.result.html( this.elements.items );
}
var oAnswerItem = $(this.options.selectors.answer.item.item + '[data-is-template=true]').clone().removeAttr('data-is-template').show();
oAnswerList.append(oAnswerItem);
oAnswerItem.find(this.options.selectors.answer.item.text).focus();
};
/**
* Удаляет вариант ответа
*
* @param {Object} oRemoveButton Кнопка удаления
*/
this.answerRemove = function(oRemoveButton) {
oRemoveButton.closest(this.options.selectors.answer.item.item).fadeOut(200, function () {
$(this).remove();
});
};
/**
* Проставляет индексы инпутам ответа
*
* @param {Object} oForm Форма добавления опроса
*/
this.answerIndex = function(oForm) {
oForm.find(this.options.selectors.answer.item.item).each(function (iIndex, oElement) {
var oAnswerItem = $(oElement),
oAnswerItemId = oAnswerItem.find(this.options.selectors.answer.item.id),
oAnswerItemText = oAnswerItem.find(this.options.selectors.answer.item.text);
oAnswerItemId.attr('name', 'answers[' + iIndex + '][id]');
oAnswerItemText.attr('name', 'answers[' + iIndex + '][title]');
}.bind(this));
};
/**
* Голосование в опросе
*
* @param {Object} oForm Форма с данными опроса
* @param {Object} oButton Копка для анимации загрузки
* @param {Boolean} bAbstain Воздержаться при голосовании
*/
this.vote = function(oForm, oButton, bAbstain) {
var oFormData = oForm.serializeJSON();
ls.hook.marker('voteBefore');
ls.ajax.submit(this.options.routers.vote, oForm, function(result) {
var oPoll = $(this.options.selectors.poll.poll + '[data-poll-id=' + oFormData.id + ']').find(this.options.selectors.poll.vote_form);
oPoll.html(result.sText);
ls.hook.run('ls_pool_vote_after', [oForm, result], oPoll);
}.bind(this), { submitButton: oButton, params: { abstain: bAbstain ? 1 : 0 } });
};
/**
* Сортировка результатов
*
* @param {Object} oPoll Блок опроса
*/
this.toggleSort = function(oPoll) {
var oButton = oPoll.find(this.options.selectors.result.sort),
oPollResult = oPoll.find(this.options.selectors.result.container),
aItems = oPollResult.find(this.options.selectors.result.item),
sSortType = oButton.hasClass(ls.options.classes.states.active) ? 'poll-item-pos' : 'poll-item-count';
aItems.sort(function (a, b) {
return $(b).data(sSortType) - $(a).data(sSortType);
});
oButton.toggleClass(ls.options.classes.states.active);
oPollResult.empty().append(aItems);
};
return this;
}).call(ls.poll || {},jQuery);
});
})(jQuery);

View file

@ -2,7 +2,7 @@
* Опросы
*
* @template polls/*.tpl
*
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
@ -10,9 +10,9 @@
.poll { margin-bottom: 15px; background: #fafafa; padding: 15px; }
.poll-title { font-size: 20px; margin-bottom: 10px; }
.poll-title { font-size: 20px; margin-bottom: 20px; }
.poll-answer-list { margin-bottom: 20px; margin-left: 0; list-style-type: none; }
.poll-answer-list { margin-bottom: 20px; margin-left: 0; list-style-type: none; }
.poll-answer-list-item { margin-bottom: 10px; }
.poll-answer-list-item:last-child { margin-bottom: 0; }
@ -32,18 +32,29 @@
.poll-result-item-chart { padding-left: 65px; }
.poll-result-item-bar { height: 10px; margin-top: 5px; background: #ccc; overflow: hidden; border-radius: 2px; }
.poll-result-item-most .poll-result-item-bar { background: #AC90DF; }
.poll-result-item--most .poll-result-item-bar { background: #AC90DF; }
.poll-result-total { color: #aaa; margin-left: 10px; }
/**
* Создание опроса
* Управление опросами
*
* @template polls/poll.form.tpl
*/
.poll-manage .fieldset-body { padding-bottom: 0; }
.poll-manage-add { margin-bottom: 15px; }
.poll-manage-list { overflow: hidden; }
.poll-manage-item { padding: 10px 70px 10px 15px; background: #fff; margin-bottom: 1px; position: relative; }
.poll-manage-item:last-child { margin-bottom: 15px; }
/**
* Форма добавления
*
* @template polls/poll.form.tpl
*/
.poll-form-answer-item { margin-bottom: 10px; padding-right: 25px; position: relative; }
.poll-form-answer-item .field,
.poll-form-answer-item:last-child { margin-bottom: 0; }
.poll-form-answer-item-remove { position: absolute; top: 7px; right: 0; cursor: pointer; }
.poll-form-list-item { padding: 10px 70px 10px 15px; background: #fff; margin-bottom: 1px; position: relative; }

View file

@ -167,7 +167,8 @@ jQuery(document).ready(function($){
/**
* Poll
*/
ls.poll.init();
$('.js-poll').lsPoll();
$('.js-poll-manage').lsPollManage();
/**

View file

@ -1 +1 @@
{include 'polls/poll.form.list.tpl'}
{include 'components/poll/poll.manage.list.tpl'}

View file

@ -0,0 +1,29 @@
{**
* Блок добавления ответа
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<li class="poll-form-answer-item js-poll-form-answer-item"
{if $bPollItemIsTemplate|default:false}data-is-template="true"{/if}
{if $bPollItemIsTemplate|default:false}style="display: none"{/if}>
{* ID *}
{include 'components/field/field.hidden.tpl'
sName = "answers[{$iPollItemIndex|default:0}][id]"
sValue = "{if $oPollItem}{$oPollItem->getId()}{/if}"
sClasses = "js-poll-form-answer-item-id"}
{* Текст *}
{include 'components/field/field.text.tpl'
sName = 'answers[]'
sValue = ($oPollItem) ? $oPollItem->getTitle() : ''
bIsDisabled = ! $bPollIsAllowUpdate|default:true
sInputClasses = 'width-full js-poll-form-answer-item-text'}
{* Кнопка удаления *}
{if $bPollIsAllowRemove|default:true}
<i class="icon-remove poll-form-answer-item-remove js-poll-form-answer-item-remove" title="{$aLang.common.remove}"></i>
{/if}
</li>

View file

@ -6,11 +6,12 @@
*}
<form action="" method="post" id="js-poll-form" data-action="{if $oPoll}update{else}add{/if}">
{* Заголовок топика *}
{include file='components/field/field.text.tpl'
{* Заголовок *}
{include 'components/field/field.text.tpl'
sName = 'poll[title]'
sValue = {($oPoll) ? $oPoll->getTitle() : '' }
sLabel = $aLang.poll.answer}
sLabel = $aLang.poll.answer
sInputAttributes="autofocus"}
{* Кол-во вариантов которые может выбрать пользователь *}
@ -20,14 +21,14 @@
<p class="mb-10">{$aLang.poll.form.fields.type.label}:</p>
{include file='components/field/field.radio.tpl'
{include 'components/field/field.radio.tpl'
sName = 'poll[type]'
sValue = 'one'
sLabel = $aLang.poll.form.fields.type.label_one
bChecked = ! $oPoll or $oPoll->getCountAnswerMax() == 1
bIsDisabled = $bDisableChangeType}
{include file='components/field/field.radio.tpl'
{include 'components/field/field.radio.tpl'
bDisplayInline = true
sName = 'poll[type]'
sValue = 'many'
@ -35,7 +36,7 @@
bChecked = $oPoll and $oPoll->getCountAnswerMax() > 1
bIsDisabled = $bDisableChangeType}
{include file='components/field/field.text.tpl'
{include 'components/field/field.text.tpl'
bDisplayInline = true
sName = 'poll[count_answer_max]'
sValue = ($oPoll) ? $oPoll->getCountAnswerMax() : 2
@ -55,21 +56,21 @@
{$aAnswers = $oPoll->getAnswers()}
{foreach $aAnswers as $oAnswer}
{include 'polls/poll.form.answers.item.tpl'
{include './poll.form.item.tpl'
oPollItem = $oAnswer
iPollItemIndex = $oAnswer@index
bPollIsAllowUpdate = $oPoll->isAllowUpdate()
bPollIsAllowRemove = $oPoll->isAllowUpdate() && ! $oAnswer->getCountVote()}
{/foreach}
{else}
{include 'polls/poll.form.answers.item.tpl'}
{include './poll.form.item.tpl'}
{/if}
</ul>
</div>
{if ! $oPoll or $oPoll->isAllowUpdate()}
<footer class="fieldset-footer">
{include file='components/button/button.tpl'
{include 'components/button/button.tpl'
sType = 'button'
sText = $aLang.common.add
sAttributes = 'title="[Ctrl + Enter]"'
@ -81,14 +82,14 @@
{* Скрытые поля *}
{if $oPoll}
{include file='components/field/field.hidden.tpl' sName='poll_id' sValue=$oPoll->getId()}
{include 'components/field/field.hidden.tpl' sName='poll_id' sValue=$oPoll->getId()}
{else}
{include file='components/field/field.hidden.tpl' sName='target[type]' sValue=$sTargetType}
{include file='components/field/field.hidden.tpl' sName='target[id]' sValue=$sTargetId}
{include 'components/field/field.hidden.tpl' sName='target[type]' sValue=$sTargetType}
{include 'components/field/field.hidden.tpl' sName='target[id]' sValue=$sTargetId}
{/if}
{include file='components/field/field.hidden.tpl' sName='target[tmp]' sValue=$sTargetTmp}
{include 'components/field/field.hidden.tpl' sName='target[tmp]' sValue=$sTargetTmp}
</form>
{* Шаблон ответа для добавления с помощью js *}
{include 'polls/poll.form.answers.item.tpl' bPollItemIsTemplate=true}
{include './poll.form.item.tpl' bPollItemIsTemplate=true}

View file

@ -0,0 +1,9 @@
{**
* Список опросов
*
* @param array $polls
*}
{foreach $polls as $poll}
{include './poll.tpl' poll=$poll}
{/foreach}

View file

@ -0,0 +1,24 @@
{**
* Добавленный опрос в блоке управления опросами
*
* @param ModulePoll_EntityPoll $oPoll Опрос
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<li class="poll-manage-item js-poll-manage-item" data-poll-id="{$oPoll->getId()}" data-poll-target-tmp="{$oPoll->getTargetTmp()}">
{* Заголовок *}
{$oPoll->getTitle()}
{* Действия *}
<ul class="user-list-small-item-actions">
{* Редактировать *}
{* Показывает модальное окно с формой редактирования опроса *}
<li class="icon-edit js-poll-manage-item-edit"
title="{$aLang.common.edit}" data-poll-id="{$oPoll->getId()}" data-poll-target-tmp="{$oPoll->getTargetTmp()}"></li>
{* Удалить *}
<li class="icon-remove js-poll-manage-item-remove" title="{$aLang.common.remove}" data-poll-id="{$oPoll->getId()}" data-poll-target-tmp="{$oPoll->getTargetTmp()}"></li>
</ul>
</li>

View file

@ -5,10 +5,10 @@
* @scripts <common>/js/poll.js
*}
<ul class="poll-form-list js-poll-form-list">
<ul class="poll-manage-list js-poll-manage-list">
{if $aPollItems}
{foreach $aPollItems as $oPoll}
{include 'polls/poll.form.list.item.tpl' oPoll=$oPoll}
{include './poll.manage.item.tpl' oPoll=$oPoll}
{/foreach}
{/if}
</ul>

View file

@ -0,0 +1,26 @@
{**
* Управления опросами (добавление/удаление/редактирование)
*
* @param string $sTargetId
* @param string $sTargetType
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<div class="fieldset poll-manage js-poll-manage" data-type="{$sTargetType}" data-target-id="{$sTargetId}">
<header class="fieldset-header">
<h3 class="fieldset-title">{$aLang.poll.polls}</h3>
</header>
<div class="fieldset-body">
{* Кнопка добавить *}
{include 'components/button/button.tpl' sText=$aLang.common.add sType='button' sClasses='poll-manage-add js-poll-manage-add'}
{* Список добавленных опросов *}
{insert name="block" block="pollFormItems" params=[
'target_type' => $sTargetType,
'target_id' => $sTargetId
]}
</div>
</div>

View file

@ -0,0 +1,43 @@
{**
* Результат опроса
*
* @param ModulePoll_EntityPoll $oPoll Опрос
*}
{* Список ответов *}
<ul class="poll-result js-poll-result">
{$answers = $oPoll->getAnswers()}
{$count = count($answers)}
{foreach $answers as $answer}
{$votes = $answer->getCountVote()}
{$percent = $oPoll->getAnswerPercent($answer)}
{* Ответ *}
<li class = "poll-result-item {if $oPoll->getCountVoteAnswerMax() == $votes}poll-result-item--most{/if} js-poll-result-item"
data-count = "{$votes}"
data-position = "{$count - $answer@index - 1}">
{* Кол-во и процент проголосовавших *}
<div class="poll-result-item-count">
<strong>{$percent}%</strong>
<span>({$votes})</span>
</div>
{* Визуальное отображения процента проголосовавших *}
<div class="poll-result-item-chart">
<div class="poll-result-item-label">{$answer->getTitle()}</div>
<div class="poll-result-item-bar" style="width: {$percent}%;"></div>
</div>
</li>
{/foreach}
</ul>
{* Кнопка сортировки *}
{include 'components/button/button.tpl' sMods='icon' sClasses='js-poll-result-sort' sIcon='icon-align-left' sAttributes="title=\"{$aLang.poll.result.sort}\""}
{* Статистика голосования *}
<span class="poll-result-total">
{$aLang.poll.result.voted_total}: {$oPoll->getCountVote()} |
{$aLang.poll.result.abstained_total}: {$oPoll->getCountAbstain()}
</span>

View file

@ -0,0 +1,15 @@
{**
* Опрос
*
* @param ModulePoll_EntityPoll $poll Опрос
*}
<div class="poll poll-type-{$poll->getTargetType()} js-poll" data-poll-id="{$poll->getId()}" data-poll-answer-max="{$poll->getCountAnswerMax()}">
<h3 class="poll-title">{$poll->getTitle()}</h3>
{if ! $poll->getVoteCurrent()}
{include './poll.vote.tpl' poll=$poll}
{else}
{include './poll.result.tpl' oPoll=$poll}
{/if}
</div>

View file

@ -0,0 +1,38 @@
{**
* Форма голосования
*
* @param ModulePoll_EntityPoll $poll Опрос
*}
{* Тип голосования *}
{* Если можно выбрать больше одного варианта, то показываем чекбоксы, иначе радио-кнопки *}
{$type = ( $poll->getCountAnswerMax() > 1 ) ? 'checkbox' : 'radio'}
{* Форма *}
<form method="post" class="js-poll-vote-form">
{* Список ответов *}
<ul class="poll-answer-list">
{foreach $poll->getAnswers() as $answer}
<li class="poll-answer-list-item js-poll-answer-list-item" data-answer-id="{$answer->getId()}">
{include "components/field/field.{$type}.tpl"
sName = 'answers[]'
sValue = $answer->getId()
sLabel = $answer->getTitle()
sClasses = 'js-poll-answer-$type'}
</li>
{/foreach}
</ul>
{include 'components/field/field.hidden.tpl' sName='id' sValue=$poll->getId()}
{if $oUserCurrent}
{* Проголосовать *}
{include 'components/button/button.tpl' sText=$aLang.poll.vote sType='button' sMods='primary' sClasses='js-poll-vote'}
{* Воздержаться *}
{include 'components/button/button.tpl' sText=$aLang.poll.abstain sType='button' sClasses='js-poll-abstain'}
{else}
{* Предупрежение: голосовать могут только авторизованные пользователи *}
{include 'components/alert/alert.tpl' sMods='info' mAlerts=$aLang.poll.only_auth}
{/if}
</form>

View file

@ -106,7 +106,7 @@
{* Вставка опросов *}
{if $oTopicType->getParam('allow_poll')}
{include file='polls/poll.form.inject.tpl'
{include file='components/poll/poll.manage.tpl'
sTargetType = 'topic'
sTargetId = ($oTopicEdit) ? $oTopicEdit->getId() : ''}
{/if}

View file

@ -17,7 +17,7 @@
{/block}
{block name='modal_content'}
{include 'polls/poll.form.tpl'}
{include 'components/poll/poll.form.tpl'}
{/block}
{block name='modal_footer_begin'}
@ -25,5 +25,5 @@
sForm = '#js-poll-form'
sText = ($oPoll) ? $aLang.common.save : $aLang.common.add
sClasses = 'js-poll-form-submit'
sMods = 'primary'}
sMods = 'primary'}
{/block}

View file

@ -1,20 +0,0 @@
{**
* Блок добавления ответа
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<li class="poll-form-answer-item js-poll-form-answer-item" {if $bPollItemIsTemplate|default:false}data-is-template="true"{/if} {if $bPollItemIsTemplate|default:false}style="display: none"{/if}>
<input type="hidden" name="answers[{$iPollItemIndex|default:0}][id]" value="{if $oPollItem}{$oPollItem->getId()}{/if}" class="js-poll-form-answer-item-id">
<input type="text"
name="answers[{$iPollItemIndex|default:0}][title]"
class="width-full js-poll-form-answer-item-text"
value="{if $oPollItem}{$oPollItem->getTitle()}{/if}"
{if ! $bPollIsAllowUpdate|default:true}disabled{/if}>
{if $bPollIsAllowRemove|default:true}
<i class="icon-remove poll-form-answer-item-remove js-poll-form-answer-item-remove" title="{$aLang.common.remove}"></i>
{/if}
</li>

View file

@ -1,29 +0,0 @@
{**
* Форма добавления
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<div class="fieldset">
<header class="fieldset-header">
<h3 class="fieldset-title">{$aLang.poll.polls}</h3>
</header>
<div class="fieldset-body">
<button class="button button-primary"
data-type="modal-toggle"
data-modal-url="{router page='ajax/poll/modal-create'}"
data-param-target_type="{$sTargetType}"
data-param-target_id="{$sTargetId}">{$aLang.common.add}</button>
<br>
<br>
{$aBlockParams = []}
{$aBlockParams.target_type = $sTargetType}
{$aBlockParams.target_id = $sTargetId}
{insert name="block" block="pollFormItems" params=$aBlockParams}
</div>
</div>

View file

@ -1,15 +0,0 @@
{**
* Добавленный опрос в форме добавления
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<li class="poll-form-list-item js-poll-form-list-item" data-poll-id="{$oPoll->getId()}" data-poll-target-tmp="{$oPoll->getTargetTmp()}">
{$oPoll->getTitle()}
<ul class="user-list-small-item-actions">
<li class="icon-edit js-poll-form-list-item-edit" title="{$aLang.common.edit}" data-type="modal-toggle" data-modal-url="{router page='ajax/poll/modal-update'}" data-param-id="{$oPoll->getId()}" data-param-target_tmp="{$oPoll->getTargetTmp()}"></li>
<li class="icon-remove js-poll-form-list-item-remove" title="{$aLang.common.remove}"></li>
</ul>
</li>

View file

@ -1,10 +0,0 @@
{**
* Список опросов
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
{foreach $aPollItems as $oPoll}
{include 'polls/poll.tpl'}
{/foreach}

View file

@ -1,33 +0,0 @@
{**
* Результат опроса
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<ul class="poll-result js-poll-result">
{$aAnswerItems = $oPoll->getAnswers()}
{$iPollItemsCount = count($aAnswerItems)}
{foreach $aAnswerItems as $oAnswer}
<li class="poll-result-item {if $oPoll->getCountVoteAnswerMax() == $oAnswer->getCountVote()}poll-result-item-most{/if} js-poll-result-item"
data-poll-item-count="{$oAnswer->getCountVote()}"
data-poll-item-pos="{$iPollItemsCount - $oAnswer@index - 1}">
<div class="poll-result-item-count">
<strong>{$oPoll->getAnswerPercent($oAnswer)}%</strong>
<span>({$oAnswer->getCountVote()})</span>
</div>
<div class="poll-result-item-chart">
<div class="poll-result-item-label">{$oAnswer->getTitle()}</div>
<div class="poll-result-item-bar" style="width: {$oPoll->getAnswerPercent($oAnswer)}%;" ></div>
</div>
</li>
{/foreach}
</ul>
{* Кнопка сортировки *}
<button class="button button-icon js-poll-result-sort" title="{$aLang.poll.result.sort}"><i class="icon-align-left"></i></button>
<span class="poll-result-total">{$aLang.poll.result.voted_total}: {$oPoll->getCountVote()} | {$aLang.poll.result.abstained_total}: {$oPoll->getCountAbstain()}</span>

View file

@ -1,54 +0,0 @@
{**
* Опрос
*
* @styles poll.css
* @scripts <common>/js/poll.js
*}
<div class="poll poll-type-{$oPoll->getTargetType()} js-poll" data-poll-id="{$oPoll->getId()}" data-poll-answer-max="{$oPoll->getCountAnswerMax()}">
<h3 class="poll-title">{$oPoll->getTitle()}</h3>
{if ! $oPoll->getVoteCurrent()}
<form action="" method="post" class="js-poll-vote-form">
<ul class="poll-answer-list">
{foreach $oPoll->getAnswers() as $oAnswer}
<li class="poll-answer-list-item js-poll-answer-list-item" data-answer-id="{$oAnswer->getId()}">
{if $oPoll->getCountAnswerMax() > 1}
{include 'components/field/field.checkbox.tpl'
sName = 'answers[]'
sValue = $oAnswer->getId()
sLabel = $oAnswer->getTitle()
sClasses = 'js-poll-answer-checkbox'}
{else}
{include 'components/field/field.radio.tpl'
sName = 'answers[]'
sValue = $oAnswer->getId()
sLabel = $oAnswer->getTitle()
sClasses = 'js-poll-answer-radio'}
{/if}
</li>
{/foreach}
</ul>
{include file='components/field/field.hidden.tpl' sName='id' sValue=$oPoll->getId()}
{if $oUserCurrent}
{include 'components/button/button.tpl'
sText = $aLang.poll.vote
sType = 'button'
sMods = 'primary'
sClasses = 'js-poll-vote'}
{include 'components/button/button.tpl'
sText = $aLang.poll.abstain
sType = 'button'
sMods = 'primary'
sClasses = 'js-poll-abstain'}
{else}
{$aLang.poll.only_auth}
{/if}
</form>
{else}
{include file='polls/poll.result.tpl' oPoll=$oPoll}
{/if}
</div>

View file

@ -57,7 +57,7 @@
{* Опросы *}
{block name='topic_content_polls'}
{if ! $bTopicList}
{include file='polls/poll.list.tpl' aPollItems=$oTopic->getPolls()}
{include file='components/poll/poll.list.tpl' polls=$oTopic->getPolls()}
{/if}
{/block}
{/block}