picviews/topic/index.html
<%- Loader('/public/stylesheets/topic/index.min.css')
.css('/public/stylesheets/topic/index.less')
.done(assets, config.site_static_host, config.mini_assets)
%>
<% if (topic.forum && topic.forum.css_text) { %>
<style>
<%= topic.forum.css_text %>
</style>
<% } %>
<%- partial('navbar', {style:'min-width: 600px;max-width: 1050px;'} ) %>
<div id="forum_topics" class="wrapper row">
<div id='content' class=" box col-md-9">
<div class='panel'>
<div class='header topic_header'>
<div class="pull-right">
<a class="user_avatar" href="/user/<%= topic.author.loginname %>">
<img src="<%= avatarPath(topic.author.avatar_url, 54) %>"
title="<%= topic.author.loginname %>"
/>
</a>
</div>
<% if (topic.forum) { %>
<a href="/forums/<%= topic.forum.id %>">
<span> 来自 <%= topic.forum.title %></span>
</a>
<%}%>
<div class="clearfix" style="height: 5px;"></div>
<h1 class="topic_full_title"><%= topic.title %></h1>
<small>
<a class="user_avatar" href="/user/<%= topic.author.loginname %>">
<%= topic.author.loginname %>
</a>
· 发布于 <%= topic.create_at_ago() %> · <%= topic.visit_count %> 次浏览
<% if (topic.create_at_ago() != topic.update_at_ago()) { %>
· 最后一次编辑是 <%= topic.update_at_ago() %>
<% } %>
</small>
</div>
<div class="cell" style="padding: 15px;">
<%- markdown(topic.linkedContent) %>
</div>
<div class="topic_buttons ">
<% if (current_user) { %>
<a href="/topic/<%= topic.id%>/<%= is_collect ? 'de_collect' : 'collect' %>" class="tb collect_btn" ><%= is_collect ? '取消收藏' : '收藏' %></a>
<% } %>
<% if (current_user && current_user.is_admin) { %>
<a href='/topic/<%= topic._id %>/top' class="tb" data-method="post">
<% if (topic.top) { %>
<i class="fa fa-lg fa-star-o" title='取消置顶'></i>
<% } else { %>
<i class="fa fa-lg fa-star" title='置顶'/></i>
<% } %>
</a>
<a href='/topic/<%= topic._id %>/good' class="tb" data-method="post">
<% if (topic.good) { %>
<i class="fa fa-lg fa-heart-o" title="取消精华"></i>
<% } else { %>
<i class="fa fa-lg fa-heart" title="加精华"></i>
<% } %>
</a>
<a href='/topic/<%= topic._id %>/lock' class="tb" data-method="post">
<% if (topic.lock) { %>
<i class="fa fa-lg fa-unlock" title='取消锁定'></i>
<% } else { %>
<i class="fa fa-lg fa-lock" title='锁定(不可再回复)'/></i>
<% } %>
</a>
<a href='/topic/<%= topic._id %>/edit' class="tb">
<i class="fa fa-lg fa-pencil-square-o" title='编辑'></i></a>
<a href='javascript:;'
data-id="<%= topic._id %>"
class='delete_topic_btn tb'>
<i class="fa fa-lg fa-trash" title='删除'></i></a>
<% } else { %>
<% if (current_user && current_user._id.equals(topic.author._id)) { %>
<a href='/topic/<%= topic._id %>/edit' class="tb">
<i class="fa fa-lg fa-pencil-square-o" title='编辑'></i></a>
<a href='javascript:;'
data-id="<%= topic._id %>"
class='delete_topic_btn tb'>
<i class="fa fa-lg fa-trash" title='删除'></i></a>
<% } %>
<% } %>
<a href='' onclick="return false;" class="tb">被浏览 <%= topic.visit_count %> 次</a>
<% if (topic.replies && topic.replies.length > 0) { %>
<a href='' onclick="return false;" class="tb">被回复 <%= topic.replies.length %> 次</a>
<% } %>
</div>
</div>
<% if (topic.replies && topic.replies.length > 0) { %>
<div class='panel pd10'>
<div class='cell'>
<span class='col_fade'><%= topic.replies.length %> 回复 · 直到 <%= topic.last_reply_at_age() %></span>
</div>
<%- partial('../reply/reply', topic.replies) %>
</div>
<% } else { %>
<div class="box transparent pd10">
<div class="cell" style="text-align: center">
<span style="color: rgba(0, 0, 0, 0.25);">目前尚无回复</span>
</div>
</div>
<% } %>
<% if (current_user && typeof(topic) !== 'undefined') { %>
<div class='panel pd10'>
<div class='header'>
<span class='col_fade'>添加回复</span>
</div>
<div class='innerTopic reply'>
<form id='reply_form' action='/<%= topic._id %>/reply' method='post'>
<div class='markdown_editor in_editor'>
<div class='markdown_in_editor'>
<textarea class='editor' name='r_content' rows='8'></textarea>
<div class='editor_buttons '>
<button type="button" class='btn' id="preview_topic_content">
<li class="fa fa-eye"></li> 预览</button>
<button type="submit" class='btn' data-loading-text="回复中.." <%= topic.lock ? 'disabled="disabled"' :'' %>>
<li class="fa fa-paper-plane"></li> 回复<%= topic.lock ? '(此主题已锁定)' : ''%></button>
</div>
</div>
</div>
<input type='hidden' name='_csrf' id="_csrf" value='<%= csrf %>'/>
</form>
</div>
</div>
<% } %>
</div>
<div id='sidebar' class="col-md-3">
<div class='panel'>
<div id="loginDiv" class="grid-item grid-item-nb">
<%- partial('../user/card', { object: current_user, as: 'user', showTopicCount: false, showPicCount: true }) %>
</div>
</div>
<div class='panel pd10'>
<div class='header'>
<span class='col_fade'>作者其它话题</span>
</div>
<div>
<% if (typeof(author_other_topics) === 'undefined' || author_other_topics.length > 0) { %>
<div class='unstyled'>
<%- partial('../topic/small', { collection: author_other_topics, as: 'topic', width: '180' }) %>
</div>
<% } else { %>
<p class="inner">无</p>
<% } %>
</div>
</div>
<div class='panel pd10'>
<div class='header'>
<span class='col_fade'>无人回复的话题</span>
</div>
<div>
<% if (typeof(no_reply_topics) !== 'undefined' && no_reply_topics.length > 0) { %>
<div class='unstyled'>
<%- partial('../topic/small', { collection: no_reply_topics, as: 'topic', width: '180' }) %>
</div>
<% } else { %>
<p class="inner">无</p>
<% } %>
</div>
</div>
<% if (!current_user || !current_user.isAdvanced) { %>
<div class='panel pd10'>
<%- partial('../static/image_ad_fix.html') %>
</div>
<% } %>
</div>
</div>
<div class="replies_history">
<div class="inner_content"></div>
<div class="anchor"></div>
</div>
<!-- 预览模态对话框 -->
<div class="modal fade" id="preview-modal">
<div class="modal-body" style="max-height: initial;">
<img src="" alt="点击内容或者外部自动关闭图片预览" id="preview-image">
</div>
</div>
<% if (current_user && typeof(topic) !== 'undefined') { %>
<!-- markdown editor -->
<%- partial('../includes/editor') %>
<script>
$(document).ready(function () {
// 获取所有回复者name
var allNames = $('.reply_author').map(function (idx, ele) {
return $(ele).text().trim();
}).toArray();
allNames.push($('.user_card .user_name').text())
allNames = _.uniq(allNames);
// END 获取所有回复者name
// 编辑器相关
$('textarea.editor').each(function () {
var editor = new Editor({
status: []
});
var $el = $(this);
$('#preview_topic_content').on('click', function (e) {
editor.togglePreview();
});
editor.render(this);
//绑定editor
$(this).data('editor', editor);
var $input = $(editor.codemirror.display.input);
$input.keydown(function (event) {
if (event.keyCode === 13 && (event.ctrlKey || event.metaKey)) {
event.preventDefault();
$el.closest('form').submit();
}
});
// at.js 配置
var codeMirrorGoLineUp = CodeMirror.commands.goLineUp;
var codeMirrorGoLineDown = CodeMirror.commands.goLineDown;
var codeMirrorNewlineAndIndent = CodeMirror.commands.newlineAndIndent;
$input.atwho({
at: '@',
data: allNames
})
.on('shown.atwho', function () {
CodeMirror.commands.goLineUp = _.noop;
CodeMirror.commands.goLineDown = _.noop;
CodeMirror.commands.newlineAndIndent = _.noop;
})
.on('hidden.atwho', function () {
CodeMirror.commands.goLineUp = codeMirrorGoLineUp;
CodeMirror.commands.goLineDown = codeMirrorGoLineDown;
CodeMirror.commands.newlineAndIndent = codeMirrorNewlineAndIndent;
});
// END at.js 配置
});
// END 编辑器相关
// 评论回复
$('#content').on('click', '.reply2_btn', function (event) {
var $btn = $(event.currentTarget);
var parent = $btn.closest('.reply_area');
var editorWrap = parent.find('.reply2_form');
parent.find('.reply2_area').prepend(editorWrap);
var textarea = editorWrap.find('textarea.editor');
var user = $btn.closest('.author_content').find('.reply_author').text().trim();
var editor = textarea.data('editor');
editorWrap.show('fast', function () {
var cm = editor.codemirror;
cm.focus();
if (cm.getValue().indexOf('@' + user) < 0) {
editor.push('@' + user + ' ');
}
});
});
$('#content').on('click', '.reply2_at_btn', function (event) {
var $btn = $(event.currentTarget);
var editorWrap = $btn.closest('.reply2_area').find('.reply2_form');
$btn.closest('.reply2_item').after(editorWrap);
var textarea = editorWrap.find('textarea.editor');
var user = $btn.closest('.reply2_item').find('.reply_author').text().trim();
var editor = textarea.data('editor');
editorWrap.show('fast', function () {
var cm = editor.codemirror;
cm.focus();
if (cm.getValue().indexOf('@' + user) < 0) {
editor.push('@' + user + ' ');
}
});
});
// END 评论回复
// 加入收藏
$('.collect_btn').click(function () {
var $me = $(this);
var action = $me.attr('action');
var data = {
topic_id: '<%= topic._id %>',
_csrf: '<%= csrf %>'
};
var $countSpan = $('.collect-topic-count');
$.post('/topic/' + action, data, function (data) {
if (data.status === 'success') {
if (action == 'collect') {
$me.val('取消收藏');
$me.attr('action', 'de_collect');
} else {
$me.val('收藏');
$me.attr('action', 'collect');
}
$me.toggleClass('span-success');
}
}, 'json');
});
// END 加入收藏
// 删除回复
$('#content').on('click', '.delete_reply_btn, .delete_reply2_btn', function (event) {
var $me = $(event.currentTarget);
if (confirm('确定要删除此回复吗?')) {
var reply_id = null;
if ($me.hasClass('delete_reply_btn')) {
reply_id = $me.closest('.reply_item').attr('reply_id');
}
if ($me.hasClass('delete_reply2_btn')) {
reply_id = $me.closest('.reply2_item').attr('reply_id');
}
var data = {
reply_id: reply_id,
_csrf: "<%- csrf %>"
};
$.post('/reply/' + reply_id + '/delete', data, function (data) {
if (data.status === 'success') {
if ($me.hasClass('delete_reply_btn')) {
$me.closest('.reply_item').remove();
}
if ($me.hasClass('delete_reply2_btn')) {
$me.closest('.reply2_item').remove();
}
}
}, 'json');
}
return false;
});
// END 删除回复
// 删除话题
$('.delete_topic_btn').click(function () {
var topicId = $(this).data('id');
if (topicId && confirm('确定要删除此话题吗?')) {
$.post('/topic/' + topicId + '/delete', {_csrf: $('#_csrf').val()}, function (result) {
if (!result.success) {
alert(result.message);
} else {
location.href = '/';
}
});
}
return false;
});
// END 删除话题
// 用户 hover 在回复框时才显示点赞按钮
$('.reply_area').hover(
function () {
$(this).find('.up_btn').removeClass('invisible');
},
function () {
var $this = $(this);
if ($this.find('.up-count').text().trim() === '') {
$this.find('.up_btn').addClass('invisible');
}
});
// END 用户 hover 在回复框时才显示点赞按钮
});
</script>
<% } %>
<script type="text/javascript">
(function () {
var timer = null; //对话框延时定时器
// 初始化 $('.replies_history')
var $repliesHistory = $('.replies_history');
var $repliesHistoryContent = $repliesHistory.find('.inner_content');
$repliesHistory.hide();
// END
// 鼠标移入对话框清除隐藏定时器;移出时隐藏对话框
$repliesHistory.on('mouseenter', function () {
clearTimeout(timer);
}).on('mouseleave', function () {
$repliesHistory.fadeOut('fast');
});
// 显示被 at 用户的本页评论
if ($('.reply2_item').length === 0) {
// 只在流式评论布局中使用
$('#content').on('mouseenter', '.reply_content a', function (e) {
clearTimeout(timer);
var $this = $(this);
if ($this.text()[0] === '@') {
var thisText = $this.text().trim();
var loginname = thisText.slice(1);
var offset = $this.offset();
var width = $this.width();
var mainOffset = $('#main').offset();
$repliesHistory.css('left', offset.left - mainOffset.left + width + 10); // magic number
$repliesHistory.css('top', offset.top - mainOffset.top - 10); // magic number
$repliesHistory.css({
'z-index': 1,
});
$repliesHistoryContent.empty();
var chats = [];
var replyToId = $this.closest('.reply_item').attr('reply_to_id');
while (replyToId) {
var $replyItem = $('.reply_item[reply_id=' + replyToId + ']');
var replyContent = $replyItem.find('.reply_content').text().trim();
if (replyContent.length > 0) {
chats.push([
$($replyItem.find('.user_avatar').html()).attr({
height: '30px',
width: '30px',
}), // avatar
(replyContent.length > 300 ? replyContent.substr(0, 300) + '...' : replyContent), // reply content
'<a href="#' + replyToId + '" class="scroll_to_original" title="查看原文">↑</a>'
]);
}
replyToId = $replyItem.attr('reply_to_id');
}
if (chats.length > 0) {
chats.reverse();
$repliesHistoryContent.append('<div class="title">查看对话</div>');
chats.forEach(function (pair, idx) {
var $chat = $repliesHistoryContent.append('<div class="item"></div>');
$chat.append(pair[0]); // 头像
$chat.append($('<span>').text(pair[1])); // 内容
$chat.append(pair[2]); // 查看原文 anchor
});
$repliesHistory.fadeIn('fast');
} else {
$repliesHistory.hide();
}
}
}).on('mouseleave', '.reply_content a', function (e) {
timer = setTimeout(function () {
$repliesHistory.fadeOut('fast');
}, 500);
});
}
// END 显示被 at 用户的本页评论
})();
// 点赞
$('.up_btn').click(function (e) {
var $this = $(this);
var replyId = $this.closest('.reply_area').attr('reply_id');
$.ajax({
url: '/reply/' + replyId + '/up',
method: 'POST',
}).done(function (data) {
if (data.success) {
$this.removeClass('invisible');
var currentCount = Number($this.next('.up-count').text().trim()) || 0;
if (data.action === 'up') {
$this.next('.up-count').text(currentCount + 1);
$this.addClass('uped');
} else {
if (data.action === 'down') {
$this.next('.up-count').text(currentCount - 1);
$this.removeClass('uped');
}
}
} else {
alert(data.message);
}
}).fail(function (xhr) {
if (xhr.status === 403) {
alert('请先登录,登陆后即可点赞。');
}
});
});
// END 点赞
// 图片预览
(function () {
var $previewModal = $('#preview-modal');
var $previewImage = $('#preview-image');
var $body = $('body'); // cache
$(document).on('click', '.markdown-text img', function (e) {
var $img = $(this);
// 图片被a标签包裹时,不显示弹层
if ($img.parent('a').length > 0) {
return;
}
showModal($img.attr('src'));
});
$previewModal.on('click', hideModal);
$previewModal.on('hidden.bs.modal', function () {
// 在预览框消失之后恢复 body 的滚动能力
$body.css('overflow-y', 'scroll');
})
$previewModal.on('shown.bs.modal', function () {
// 修复上次滚动留下的痕迹,可能会导致短暂的闪烁,不过可以接受
// TODO: to be promote
$previewModal.scrollTop(0);
})
function showModal(src) {
$previewImage.attr('src', src);
$previewModal.modal('show');
// 禁止 body 滚动
$body.css('overflow-y', 'hidden');
}
function hideModal() {
$previewModal.modal('hide');
}
})()
// END 图片预览
</script>
<% if (topic.forum && topic.forum.js_text) { %>
<script type="text/javascript">
<%- topic.forum.js_text %>
</script>
<% } %>