2013-05-23 20:15:54 +03:00
|
|
|
|
/**
|
|
|
|
|
* Комментарии
|
2014-02-17 10:26:20 +02:00
|
|
|
|
*
|
2013-08-29 12:30:04 +03:00
|
|
|
|
* @module ls/comments
|
2014-02-17 10:26:20 +02:00
|
|
|
|
*
|
2013-08-29 12:30:04 +03:00
|
|
|
|
* @license GNU General Public License, version 2
|
|
|
|
|
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
|
|
|
|
|
* @author Denis Shakhov <denis.shakhov@gmail.com>
|
2013-05-23 20:15:54 +03:00
|
|
|
|
*/
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
(function($) {
|
2014-02-17 10:26:20 +02:00
|
|
|
|
"use strict";
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
$.widget( "livestreet.lsComments", {
|
|
|
|
|
/**
|
|
|
|
|
* Дефолтные опции
|
|
|
|
|
*/
|
|
|
|
|
options: {
|
|
|
|
|
// Ссылки
|
|
|
|
|
urls: {
|
|
|
|
|
// Добавление комментария
|
|
|
|
|
add: null,
|
|
|
|
|
// Подгрузка новых комментариев
|
|
|
|
|
load: null,
|
|
|
|
|
// Показать/скрыть комментарий
|
|
|
|
|
hide: aRouter['ajax'] + 'comment/delete/',
|
|
|
|
|
// Обновление текста комментария
|
|
|
|
|
text: aRouter['ajax'] + 'comment/load/',
|
|
|
|
|
// Обновление комментария
|
|
|
|
|
update: aRouter['ajax'] + 'comment/update/'
|
2013-01-03 13:27:40 +02:00
|
|
|
|
},
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Селекторы
|
|
|
|
|
selectors: {
|
|
|
|
|
// Блок с превью текста
|
|
|
|
|
preview: '.js-comment-preview',
|
|
|
|
|
// Кнопка свернуть/развернуть все
|
|
|
|
|
fold_all_toggle: '.js-comments-fold-all-toggle',
|
|
|
|
|
// Заголовок
|
|
|
|
|
title: '.js-comments-title',
|
|
|
|
|
// Кнопка "Оставить комментарий"
|
|
|
|
|
reply_root: '.js-comment-reply-root',
|
|
|
|
|
// Блок с комментариями
|
|
|
|
|
comment_list: '.js-comment-list',
|
|
|
|
|
// Подписаться на новые комментарии
|
|
|
|
|
subscribe: '.js-comments-subscribe',
|
2014-07-25 19:50:19 +03:00
|
|
|
|
// Сообщение о пустом списке
|
|
|
|
|
empty: '.js-comments-empty',
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Комментарий
|
|
|
|
|
comment: {
|
|
|
|
|
comment: '.js-comment',
|
|
|
|
|
wrapper: '.js-comment-wrapper',
|
|
|
|
|
reply: '.js-comment-reply',
|
|
|
|
|
fold: '.js-comment-fold',
|
|
|
|
|
remove: '.js-comment-remove',
|
|
|
|
|
update: '.js-comment-update',
|
|
|
|
|
update_timer: '.js-comment-update-timer',
|
|
|
|
|
scroll_to_child: '.js-comment-scroll-to-child',
|
|
|
|
|
scroll_to_parent: '.js-comment-scroll-to-parent'
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Форма добавления
|
|
|
|
|
form: {
|
|
|
|
|
form: '.js-comment-form',
|
|
|
|
|
text: '.js-comment-form-text',
|
|
|
|
|
submit: '.js-comment-form-submit',
|
|
|
|
|
preview: '.js-comment-form-preview',
|
|
|
|
|
update_submit: '.js-comment-form-update-submit',
|
|
|
|
|
update_cancel: '.js-comment-form-update-cancel',
|
|
|
|
|
comment_id: '#form_comment_reply'
|
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
},
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Классы
|
|
|
|
|
classes: {
|
|
|
|
|
states: {
|
|
|
|
|
current: 'comment--current',
|
|
|
|
|
new: 'comment--new',
|
|
|
|
|
deleted: 'comment--deleted',
|
|
|
|
|
self: 'comment--self'
|
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
},
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Использовать визуальный редактор или нет
|
|
|
|
|
wysiwyg: null,
|
|
|
|
|
// Включить/выключить функцию сворачивания
|
|
|
|
|
folding: true,
|
|
|
|
|
// Показать/скрыть форму по умолчанию
|
|
|
|
|
show_form: false
|
2013-01-03 13:27:40 +02:00
|
|
|
|
},
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Конструктор
|
|
|
|
|
*
|
|
|
|
|
* @constructor
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
|
|
|
|
_create: function () {
|
2014-06-24 16:29:04 +03:00
|
|
|
|
var _this = this;
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Получаем элементы
|
|
|
|
|
this.form = this.element.find(this.options.selectors.form.form);
|
|
|
|
|
|
|
|
|
|
this.elements = {
|
|
|
|
|
title: this.element.find(this.options.selectors.title),
|
|
|
|
|
reply_root: this.element.find(this.options.selectors.reply_root),
|
|
|
|
|
fold_all_toggle: this.element.find(this.options.selectors.fold_all_toggle),
|
|
|
|
|
comment_list: this.element.find(this.options.selectors.comment_list),
|
|
|
|
|
subscribe: this.element.find(this.options.selectors.subscribe),
|
2014-07-25 19:50:19 +03:00
|
|
|
|
empty: this.element.find(this.options.selectors.empty),
|
2014-06-11 11:58:32 +03:00
|
|
|
|
form: {
|
|
|
|
|
text: this.form.find(this.options.selectors.form.text),
|
|
|
|
|
submit: this.form.find(this.options.selectors.form.submit),
|
|
|
|
|
preview: this.form.find(this.options.selectors.form.preview),
|
|
|
|
|
update_cancel: this.form.find(this.options.selectors.form.update_cancel),
|
|
|
|
|
update_submit: this.form.find(this.options.selectors.form.update_submit),
|
|
|
|
|
comment_id: this.form.find(this.options.selectors.form.comment_id)
|
|
|
|
|
}
|
|
|
|
|
};
|
2013-05-23 20:15:54 +03:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// ID комментария помеченного как текущий
|
|
|
|
|
this.currentCommentId = null;
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Список комментариев на странице
|
|
|
|
|
this.comments = $(this.options.selectors.comment.comment);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// ID комментария после которого отображается форма
|
|
|
|
|
this.formTargetId = 0;
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Получаем ID объекта к которому оставлен комментарий
|
|
|
|
|
this.targetId = this.element.data('target-id');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Получаем тип объекта
|
|
|
|
|
this.targetType = this.element.data('target-type');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// ID последнего добавленного комментария
|
|
|
|
|
this.commentLastId = this.element.data('comment-last-id');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Показываем кнопку свернуть у комментариев с дочерними комментариями
|
|
|
|
|
this.checkFolding();
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Обновление таймеров у кнопок редактирования
|
|
|
|
|
this.initUpdateTimers();
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Показываем/скрываем форму по умолчанию
|
|
|
|
|
! this.options.show_form && this.formToggle(0);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
//
|
|
|
|
|
// События
|
|
|
|
|
//
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Навигация по комментариям
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.document.on('click' + this.eventNamespace, this.options.selectors.comment.scroll_to_parent, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this);
|
|
|
|
|
|
|
|
|
|
_this.scrollToParentComment(element.data('id'), element.data('parent-id'));
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Показывает / скрывает форму комментирования
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.document.on('click' + this.eventNamespace, this.options.selectors.comment.reply, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
_this.formToggle($(this).data('id'), true, false, false);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Превью текста
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this._on( this.elements.form.preview, { 'click': this.previewShow } );
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
// Отправка формы
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this._on( this.form, { 'submit': function (e) {
|
|
|
|
|
this.add( this.form, this.form.data('target-id'), this.form.data('target-type') );
|
2014-02-17 10:26:20 +02:00
|
|
|
|
e.preventDefault();
|
2014-06-24 16:29:04 +03:00
|
|
|
|
}});
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.elements.form.text.bind( 'keydown' + this.eventNamespace, 'ctrl+return', function() { _this.form.submit() } );
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Удаление
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.element.on('click' + this.eventNamespace, this.options.selectors.comment.remove, function(e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this),
|
|
|
|
|
commentId = element.data('id');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
_this.toggle(element, commentId);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Редактирование
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.element.on('click' + this.eventNamespace, this.options.selectors.comment.update, function(e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this),
|
|
|
|
|
commentId = element.data('id');
|
2014-04-25 08:24:15 +03:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
_this.formToggle(commentId, false, true);
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Отмена редактирования
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.elements.form.update_cancel.on('click' + this.eventNamespace, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.formToggle(this.formTargetId, false, true);
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}.bind(this));
|
2014-03-04 10:26:29 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Сохранение после редактирования
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.elements.form.update_submit.on('click' + this.eventNamespace, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.submitCommentUpdate(this.formTargetId);
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
}.bind(this));
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Подписаться/отписаться от новых комментариев
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.elements.subscribe.on('click' + this.eventNamespace, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this),
|
|
|
|
|
isActive = element.hasClass('active');
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.subscribe.toggle(element.data('type') + '_new_comment', element.data('target-id'), '', ! isActive);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
if ( isActive ) {
|
|
|
|
|
element.removeClass('active').text( ls.lang.get('comments.subscribe') );
|
|
|
|
|
} else {
|
|
|
|
|
element.addClass('active').text( ls.lang.get('comments.unsubscribe') );
|
|
|
|
|
}
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Сворачивание
|
|
|
|
|
if ( this.options.folding ) {
|
|
|
|
|
// Свернуть/развернуть все
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.elements.fold_all_toggle.on('click' + this.eventNamespace, function (e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this);
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
if ( ! element.hasClass('active') ) {
|
|
|
|
|
_this.foldAll();
|
|
|
|
|
element.addClass('active').text( ls.lang.get('comments.folding.unfold_all') );
|
|
|
|
|
} else {
|
|
|
|
|
_this.unfoldAll();
|
|
|
|
|
element.removeClass('active').text( ls.lang.get('comments.folding.fold_all') );
|
|
|
|
|
}
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Свернуть/развернуть
|
2014-06-24 16:29:04 +03:00
|
|
|
|
this.element.on('click' + this.eventNamespace, this.options.selectors.comment.fold, function(e) {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var element = $(this),
|
|
|
|
|
comment = _this.getCommentById(element.data('id'));
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
_this[ element.hasClass(ls.options.classes.states.open) ? 'fold' : 'unfold' ](comment);
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
e.preventDefault();
|
|
|
|
|
});
|
2014-02-17 10:26:20 +02:00
|
|
|
|
}
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.hook.run('ls_comments_init_after',[],this);
|
|
|
|
|
},
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Добавляет комментарий
|
|
|
|
|
*/
|
|
|
|
|
add: function() {
|
|
|
|
|
// Получаем данные формы до ее блокировки
|
|
|
|
|
var data = this.form.serializeJSON();
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.utils.formLock(this.form);
|
|
|
|
|
this.previewHide();
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.ajax.load(this.options.urls.add, data, function(response) {
|
|
|
|
|
if (response.bStateError) {
|
|
|
|
|
ls.msg.error(null, response.sMsg);
|
|
|
|
|
} else {
|
|
|
|
|
this.elements.form.text.val('');
|
|
|
|
|
this.load(response.sCommentId, true);
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.hook.run('ls_comments_add_after', [this.form, this.targetId, this.targetType, response]);
|
|
|
|
|
}
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.utils.formUnlock(this.form);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
2013-05-07 01:56:46 +03:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Скрыть/восстановить комментарий
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} toggle Кнопка скрыть/восстановить комментарий
|
|
|
|
|
* @param {Number} commentId ID добавляемого комментария
|
|
|
|
|
*/
|
|
|
|
|
toggle: function(toggle, commentId) {
|
|
|
|
|
var url = this.options.urls.hide,
|
|
|
|
|
params = { idComment: commentId };
|
|
|
|
|
|
|
|
|
|
ls.hook.marker('toggleBefore');
|
|
|
|
|
|
|
|
|
|
ls.ajax.load(url, params, function(response) {
|
|
|
|
|
if (response.bStateError) {
|
|
|
|
|
ls.msg.error(null, response.sMsg);
|
|
|
|
|
} else {
|
|
|
|
|
ls.msg.notice(null, response.sMsg);
|
|
|
|
|
|
|
|
|
|
this.getCommentById(commentId).removeClass(
|
|
|
|
|
this.options.classes.states.self + ' ' +
|
|
|
|
|
this.options.classes.states.new + ' ' +
|
|
|
|
|
this.options.classes.states.deleted + ' ' +
|
|
|
|
|
this.options.classes.states.current
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (response.bState) {
|
|
|
|
|
this.getCommentById(commentId).addClass(this.options.classes.states.deleted);
|
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
toggle.text(response.sTextToggle);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.hook.run('ls_comments_toggle_after',[toggle, commentId, response]);
|
2013-01-03 13:27:40 +02:00
|
|
|
|
}
|
2014-06-11 11:58:32 +03:00
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Подгружает новые комментарии
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} сommentSelfId (undefined) ID добавляемого комментария
|
|
|
|
|
* @param {Boolean} flush (true) Удалять подсветку у текущих новых комментариев или нет
|
|
|
|
|
*/
|
|
|
|
|
load: function(сommentSelfId, flush, callbacks) {
|
|
|
|
|
flush = typeof flush === 'undefined' ? true : flush;
|
|
|
|
|
|
|
|
|
|
var params = {
|
|
|
|
|
idCommentLast: this.commentLastId,
|
|
|
|
|
idTarget: this.targetId,
|
|
|
|
|
typeTarget: this.targetType,
|
|
|
|
|
// TODO: Fix
|
|
|
|
|
// bUsePaging: this.elements.toolbar.use_paging.val() ? 1 : 0
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
params.selfIdComment = сommentSelfId || undefined;
|
|
|
|
|
|
|
|
|
|
ls.ajax.load(this.options.urls.load, params, function(response) {
|
|
|
|
|
if (response.bStateError) {
|
|
|
|
|
ls.msg.error(null, response.sMsg);
|
|
|
|
|
} else {
|
|
|
|
|
var сommentsLoaded = response.aComments,
|
|
|
|
|
сountLoaded = сommentsLoaded.length;
|
|
|
|
|
|
|
|
|
|
// Убираем подсветку у текущего комментария
|
|
|
|
|
this.getCommentCurrent().removeClass(this.options.classes.states.current);
|
|
|
|
|
this.currentCommentId = null;
|
|
|
|
|
|
|
|
|
|
// Убираем подсветку у новых комментариев
|
|
|
|
|
if ( flush ) this.getCommentsNew().removeClass(this.options.classes.states.new);
|
|
|
|
|
|
|
|
|
|
// Если комментарии подгружаются после сабмита формы текущим пользователем
|
|
|
|
|
if ( сommentSelfId ) this.formToggle(this.formTargetId, true);
|
|
|
|
|
|
2014-07-25 19:50:19 +03:00
|
|
|
|
// Скрываем сообщение о пустом списке
|
|
|
|
|
this.getComments().length == 0 && this.elements.empty.hide();
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Вставляем новые комментарии
|
|
|
|
|
$.each(сommentsLoaded, function(index, item) {
|
|
|
|
|
var сomment = $( $.trim(item.html) );
|
|
|
|
|
|
|
|
|
|
this.comments = this.comments.add(сomment);
|
|
|
|
|
this.insert(сomment, item.id, item.idParent);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
|
|
// Обновляем данные
|
|
|
|
|
if ( сountLoaded && response.iMaxIdComment ) {
|
|
|
|
|
this.commentLastId = response.iMaxIdComment;
|
|
|
|
|
|
|
|
|
|
// Обновляем кол-во комментариев в заголовке
|
|
|
|
|
this.elements.title.text( ls.i18n.pluralize(this.comments.length, 'comments.comments_declension') );
|
|
|
|
|
|
|
|
|
|
// Обновляем блок активности
|
|
|
|
|
// TODO: Fix
|
|
|
|
|
$('#js-stream-update').click();
|
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Проверяем сворачивание
|
|
|
|
|
if ( this.options.folding ) {
|
|
|
|
|
this.checkFolding();
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Разворачиваем все ветки если идет просто подгрузка комментариев
|
|
|
|
|
// или если при добавления комментария текущим пользователем
|
|
|
|
|
// помимо этого комментария подгружаются еще и ранее добавленные комментарии
|
|
|
|
|
if ( ( ! сommentSelfId && сountLoaded ) || ( сommentSelfId && сountLoaded - 1 > 0 ) ) this.unfoldAll();
|
2013-01-03 13:27:40 +02:00
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Прокручиваем к комментарию который оставил текущий пользователь
|
|
|
|
|
if ( сommentSelfId ) this.scrollToComment( this.getCommentById(сommentSelfId) );
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Обновляем таймеры
|
|
|
|
|
this.initUpdateTimers();
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-24 16:29:04 +03:00
|
|
|
|
callbacks && $.proxy( callbacks.success, this )();
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.hook.run('ls_comments_load_after', [ this.targetId, this.targetType, сommentSelfId, flush, response ]);
|
|
|
|
|
}
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-24 16:29:04 +03:00
|
|
|
|
callbacks && $.proxy( callbacks.done, this )();
|
2014-06-11 11:58:32 +03:00
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Вставка комментария
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} сomment Комментарий
|
|
|
|
|
* @param {Number} commentId ID добавляемого комментария
|
|
|
|
|
* @param {Number} commentParentId (optional) ID родительского комментария
|
|
|
|
|
*/
|
|
|
|
|
insert: function(comment, commentId, commentParentId) {
|
|
|
|
|
var commentWrapper = $('<div class="comment-wrapper js-comment-wrapper" data-id="' + commentId + '"></div>').append(comment);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
if (commentParentId) {
|
|
|
|
|
// Получаем обертку родительского комментария
|
|
|
|
|
var wrapper = $(this.options.selectors.comment.wrapper + '[data-id=' + commentParentId + ']');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
// Проверяем чтобы уровень вложенности комментариев была не больше значения заданного в конфиге
|
|
|
|
|
if (wrapper.parentsUntil(this.elements.comment_list).length == ls.registry.get('comment_max_tree')) {
|
|
|
|
|
wrapper = wrapper.parent(this.options.selectors.comment.wrapper);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
wrapper.append(commentWrapper);
|
|
|
|
|
} else {
|
|
|
|
|
this.elements.comment_list.append(commentWrapper);
|
2013-01-03 13:27:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.hook.run('ls_comment_insert_after', arguments, commentWrapper);
|
|
|
|
|
},
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Предпросмотр комментария
|
|
|
|
|
*/
|
|
|
|
|
previewShow: function() {
|
|
|
|
|
if ( ! this.elements.form.text.val() ) return;
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
var preview = $('<div class="comment-preview text js-comment-preview" data-id="' + this.formTargetId +'"></div>');
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.previewHide();
|
|
|
|
|
this.form.before(preview);
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
ls.utils.textPreview(this.elements.form.text, preview, false);
|
|
|
|
|
},
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-04-25 08:24:15 +03:00
|
|
|
|
/**
|
2014-06-11 11:58:32 +03:00
|
|
|
|
* Предпросмотр комментария
|
2014-04-25 08:24:15 +03:00
|
|
|
|
*/
|
2014-06-11 11:58:32 +03:00
|
|
|
|
previewHide: function() {
|
|
|
|
|
this.element.find(this.options.selectors.preview).remove();
|
|
|
|
|
},
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
/**
|
|
|
|
|
* Показывает/скрывает форму комментирования
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария после которого нужно показать форму
|
|
|
|
|
* @param {Boolean} focus Переводить фокус на инпут с текстом или нет
|
|
|
|
|
*/
|
|
|
|
|
formToggle: function(commentId, focus, update, reset) {
|
|
|
|
|
update = update || false,
|
|
|
|
|
focus = typeof focus === 'undefined' ? true : focus;
|
|
|
|
|
reset = typeof reset === 'undefined' ? true : reset;
|
2014-02-17 10:26:20 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.previewHide();
|
2013-01-03 13:27:40 +02:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
if ( ( ! update && this.form.data('update') ) || reset ) this.elements.form.text.val('');
|
2014-04-25 08:24:15 +03:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.form.data('update', false);
|
2014-04-25 08:24:15 +03:00
|
|
|
|
|
2014-06-11 11:58:32 +03:00
|
|
|
|
if ( this.formTargetId == commentId && this.form.is(':visible') ) {
|
|
|
|
|
this.form.hide();
|
|
|
|
|
this.formTargetId = 0;
|
|
|
|
|
return;
|
2014-04-25 08:24:15 +03:00
|
|
|
|
}
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
this.form.insertAfter(commentId ? this.getCommentById(commentId) : this.elements.reply_root).show();
|
|
|
|
|
this.elements.form.comment_id.val(commentId);
|
|
|
|
|
|
|
|
|
|
// Показываем необходимые кнопки
|
|
|
|
|
if (update) {
|
|
|
|
|
this.form.data('update', true);
|
|
|
|
|
this.elements.form.update_cancel.show();
|
|
|
|
|
this.elements.form.update_submit.show();
|
|
|
|
|
this.elements.form.submit.hide();
|
|
|
|
|
|
|
|
|
|
// Загружаем исходный текст комментария
|
|
|
|
|
this.loadCommentUpdate(commentId);
|
2014-04-25 08:24:15 +03:00
|
|
|
|
} else {
|
2014-06-11 11:58:32 +03:00
|
|
|
|
this.elements.form.update_cancel.hide();
|
|
|
|
|
this.elements.form.update_submit.hide();
|
|
|
|
|
this.elements.form.submit.show();
|
2014-04-25 08:24:15 +03:00
|
|
|
|
}
|
2014-06-11 11:58:32 +03:00
|
|
|
|
|
|
|
|
|
this.formTargetId = commentId;
|
|
|
|
|
|
|
|
|
|
if ( focus ) this.elements.form.text.focus();
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Обновление текста комментария
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария
|
|
|
|
|
*/
|
|
|
|
|
loadCommentUpdate: function(commentId) {
|
|
|
|
|
var url = this.options.urls.text,
|
|
|
|
|
params = { idComment: commentId };
|
|
|
|
|
|
|
|
|
|
ls.utils.formLock(this.form);
|
|
|
|
|
ls.hook.marker('loadBefore');
|
|
|
|
|
|
|
|
|
|
ls.ajax.load(url, params, function(response) {
|
|
|
|
|
if (response.bStateError) {
|
|
|
|
|
ls.msg.error(null, response.sMsg);
|
|
|
|
|
} else {
|
|
|
|
|
this.elements.form.text.val(response.sText);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ls.hook.run('ls_comments_load_comment_update_after', [commentId, response]);
|
|
|
|
|
|
|
|
|
|
ls.utils.formUnlock(this.form);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Редактирование комментария
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария
|
|
|
|
|
*/
|
|
|
|
|
submitCommentUpdate: function(commentId) {
|
|
|
|
|
var data = this.form.serializeJSON(),
|
|
|
|
|
url = this.options.urls.update;
|
|
|
|
|
|
|
|
|
|
ls.utils.formLock(this.form);
|
|
|
|
|
this.previewHide();
|
|
|
|
|
|
|
|
|
|
data.comment_id = commentId;
|
|
|
|
|
|
|
|
|
|
ls.ajax.load(url, data, function(response) {
|
|
|
|
|
if (response.bStateError) {
|
|
|
|
|
ls.msg.error(null, response.sMsg);
|
|
|
|
|
} else {
|
|
|
|
|
var comment = this.getCommentById(commentId),
|
|
|
|
|
commentNew = $( $.trim(response.sHtml) );
|
|
|
|
|
|
|
|
|
|
this.removeCommentById(commentId);
|
|
|
|
|
this.comments = this.comments.add(commentNew);
|
|
|
|
|
|
|
|
|
|
comment.replaceWith( commentNew );
|
|
|
|
|
comment.find(this.options.selectors.comment.update_timer).stopTime();
|
|
|
|
|
|
|
|
|
|
this.formToggle(commentId, true);
|
|
|
|
|
this.initUpdateTimers();
|
|
|
|
|
this.checkFolding(commentNew);
|
|
|
|
|
this.scrollToComment(commentNew);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ls.hook.run('ls_comments_submit_comment_update_after', [this.form, commentId, response]);
|
|
|
|
|
|
|
|
|
|
ls.utils.formUnlock(this.form);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Иниц-ия таймеров
|
|
|
|
|
* TODO: Fix
|
|
|
|
|
*/
|
|
|
|
|
initUpdateTimers: function() {
|
|
|
|
|
var _this=this;
|
|
|
|
|
$(this.options.selectors.comment.update_timer).each(function(k,el){
|
|
|
|
|
el=$(el);
|
|
|
|
|
if (!el.data('isInit')) {
|
|
|
|
|
el.data('isInit',true);
|
|
|
|
|
el.everyTime(1000,function(){
|
|
|
|
|
var seconds=parseInt(el.data('seconds'));
|
|
|
|
|
seconds--;
|
|
|
|
|
el.data('seconds',seconds);
|
|
|
|
|
if (seconds>0) {
|
|
|
|
|
el.text(ls.utils.timeRemaining(seconds));
|
|
|
|
|
} else {
|
|
|
|
|
el.parents(_this.options.selectors.comment.comment)
|
|
|
|
|
.find(_this.options.selectors.comment.update).hide();
|
|
|
|
|
el.stopTime();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Показывает кнопку сворачивания у комментариев с дочерними комментариями
|
|
|
|
|
* и скрывает у комментариев без них
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} сomment (optional) Комментарий у которого нужно проверить наличие дочерних комментарев, если не указан то проверяется у всех
|
|
|
|
|
*/
|
|
|
|
|
checkFolding: function(comment) {
|
|
|
|
|
if ( ! this.options.folding ) return;
|
|
|
|
|
|
|
|
|
|
var comments = comment ? comment : this.getComments();
|
|
|
|
|
|
|
|
|
|
comments.each(function (index, сomment) {
|
|
|
|
|
var сomment = $(сomment);
|
|
|
|
|
|
|
|
|
|
сomment.find(this.options.selectors.comment.fold)[ сomment.nextAll(this.options.selectors.comment.wrapper).length ? 'show' : 'hide' ]();
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Сворачивает ветку комментариев
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} сomment Комментарий у которого нужно скрыть дочернии комментарии
|
|
|
|
|
*/
|
|
|
|
|
fold: function(сomment) {
|
|
|
|
|
сomment.removeClass(ls.options.classes.states.open).nextAll(this.options.selectors.comment.wrapper).hide();
|
|
|
|
|
сomment.find(this.options.selectors.comment.fold).removeClass(ls.options.classes.states.open);
|
|
|
|
|
|
|
|
|
|
this.onFold(сomment);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Разворачивает ветку комментариев
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} comment Комментарий у которого нужно показать дочернии комментарии
|
|
|
|
|
*/
|
|
|
|
|
unfold: function(comment) {
|
|
|
|
|
comment.addClass(ls.options.classes.states.open).nextAll(this.options.selectors.comment.wrapper).show();
|
|
|
|
|
comment.find(this.options.selectors.comment.fold).addClass(ls.options.classes.states.open);
|
|
|
|
|
|
|
|
|
|
this.onUnfold(comment);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Коллбэк вызываемый после сворачивания ветки комментариев
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} comment Комментарий
|
|
|
|
|
*/
|
|
|
|
|
onFold: function(comment) {
|
|
|
|
|
comment.find(this.options.selectors.comment.fold).find('a').text(ls.lang.get('comments.folding.unfold'));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Коллбэк вызываемый после разворачивания ветки комментариев
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} comment Комментарий
|
|
|
|
|
*/
|
|
|
|
|
onUnfold: function(comment) {
|
|
|
|
|
comment.find(this.options.selectors.comment.fold).find('a').text(ls.lang.get('comments.folding.fold'));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Сворачивает все ветки комментариев
|
|
|
|
|
*/
|
|
|
|
|
foldAll: function() {
|
|
|
|
|
this.getComments().filter('.' + ls.options.classes.states.open).each(function (index, comment) {
|
|
|
|
|
this.fold( $(comment) );
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Разворачивает все ветки комментариев
|
|
|
|
|
*/
|
|
|
|
|
unfoldAll: function() {
|
|
|
|
|
this.getComments().not('.' + ls.options.classes.states.open).each(function (index, comment) {
|
|
|
|
|
this.unfold( $(comment) );
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Прокрутка к комментарию
|
|
|
|
|
*
|
|
|
|
|
* @param {jQuery} comment Комментарий
|
|
|
|
|
*/
|
|
|
|
|
scrollToComment: function(comment) {
|
|
|
|
|
this.setCommentCurrent(comment);
|
|
|
|
|
|
|
|
|
|
$.scrollTo(comment, 1000, { offset: -250 });
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Прокрутка к родительскому комментарию
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария
|
|
|
|
|
* @param {Number} commentParentId ID родительского комментария
|
|
|
|
|
*/
|
|
|
|
|
scrollToParentComment: function(commentId, commentParentId) {
|
|
|
|
|
var child = this.getCommentById(commentId),
|
|
|
|
|
parent = this.getCommentById(commentParentId),
|
|
|
|
|
scroll = parent.find(this.options.selectors.comment.scroll_to_child);
|
|
|
|
|
|
|
|
|
|
// Скрываем кнопку прокрутки к дочернему комментарию у текущего комментария
|
|
|
|
|
this.getCommentCurrent().find(this.options.selectors.comment.scroll_to_child).off().hide();
|
|
|
|
|
|
|
|
|
|
// Прокрутка к родительскому комментарию
|
|
|
|
|
this.scrollToComment(parent);
|
|
|
|
|
|
|
|
|
|
// Прокрутка обратно к дочернему комментарию
|
|
|
|
|
scroll.show().off().one('click', function() {
|
|
|
|
|
scroll.hide();
|
|
|
|
|
this.scrollToComment(child);
|
|
|
|
|
}.bind(this));
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Получает комментарий по его ID
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария
|
|
|
|
|
* @return {jQuery} Комментарий
|
|
|
|
|
*/
|
|
|
|
|
getCommentById: function(commentId) {
|
|
|
|
|
return this.getComments().filter('[data-id=' + commentId + ']');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Удаляет комментарий по его ID
|
|
|
|
|
*
|
|
|
|
|
* @param {Number} commentId ID комментария
|
|
|
|
|
*/
|
|
|
|
|
removeCommentById: function(commentId) {
|
|
|
|
|
this.comments = this.getComments().not('[data-id=' + commentId + ']');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Устанавливает текущий комментарий
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} comment
|
|
|
|
|
*/
|
|
|
|
|
setCommentCurrent: function(comment) {
|
|
|
|
|
this.getCommentCurrent().removeClass(this.options.classes.states.current);
|
|
|
|
|
comment.addClass(this.options.classes.states.current);
|
|
|
|
|
this.currentCommentId = comment.data('id');
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Получает текущий комментарий
|
|
|
|
|
*
|
|
|
|
|
* @return {jQuery} Текущий комментарий
|
|
|
|
|
*/
|
|
|
|
|
getCommentCurrent: function() {
|
|
|
|
|
return this.getCommentById(this.currentCommentId);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Получает новые комментарии
|
|
|
|
|
*
|
|
|
|
|
* @return {Array} Массив с новыми комментариями
|
|
|
|
|
*/
|
|
|
|
|
getCommentsNew: function() {
|
|
|
|
|
return this.getComments().filter('.' + this.options.classes.states.new);
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Получает комментарии
|
|
|
|
|
*
|
|
|
|
|
* @return {Array} Массив с комментариями
|
|
|
|
|
*/
|
|
|
|
|
getComments: function() {
|
|
|
|
|
return this.comments;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
})(jQuery);
|