comments-data.js
是测试数据:Download here jquery-comments.js
创建整个评论系统:Download here jquery-comments.min.js
(如果需要):Download here 我有一个包含“文章”列表的视图,该列表中的每个“文章”上都有一个“阅读更多”按钮。当我单击“阅读更多”按钮时,将打开一个模态,其中包含jquery注释的局部视图。但是,当我搜索ping通的用户(使用@
符号时,用户列表不是按textarea
显示,而是显示在模式上方(远离{{1 }}。
下面是一张图片,然后在下面是我的代码。您将在图像的底部看到我添加了“ @”符号,并且用户列表显示在顶部,应该在textarea
旁边。似乎当我单击列表中较低的文章时,按“ @”符号时,用户列表的显示位置也将较高:
下面是填充“文章”的部分,从中调用模态:
textarea
这放置在页面的顶部(在@model appname.ViewModels.VM下):
@{
int iGroupNameId = 0;
int iTotalArticles = 0;
foreach (var groupItems in Model.ArticleGroups)
{
iTotalArticles = Model.ArticlesList.Where(x => x.fkiGroupNameId == groupItems.pkiKnowledgeSharingCenterGroupsId).Count();
if (iTotalArticles > 0)
{
<div style="background: linear-gradient(#B5012E, darkred); margin: 10px; padding: 10px; font-weight: bold; color: white; text-transform: uppercase;">@groupItems.GroupName</div><div class="container" style="width:100%">
@if (groupItems.pkiKnowledgeSharingCenterGroupsId != iGroupNameId)
{
foreach (var item in Model.ArticlesList.Where(x => x.fkiGroupNameId == groupItems.pkiKnowledgeSharingCenterGroupsId))
{
<div class="row">
<div class="col-md-4">
@if (User.IsInRole("Administrator"))
{
<div class="pull-right">
<div class="btn-group">
<button class="btn dropdown-toggle btn-xs btn-info" data-toggle="dropdown">
<i class="fa fa-gear"></i> <i class="fa fa-caret-down"></i>
</button>
<ul class="dropdown-menu pull-right">
<li>
<a href="@Url.Action("EditArticle", "ILearn", new { id = item.KnowledgeSharingArticlesId })">Edit</a>
</li>
<li class="divider"></li>
<li>
<a href="@Url.Action("DeleteArticle", "ILearn", new { id = item.KnowledgeSharingArticlesId })">Delete</a>
</li>
</ul>
</div>
</div>
}
<img src="@item.ArticleImage" class="img-responsive" alt="img" style="width:350px;height:200px">
<ul class="list-inline padding-10">
<li>
<i class="fa fa-calendar"></i>
@item.DateTimeStamp.ToLongDateString()
</li>
<li>
<i class="fa fa-comments"></i>
@item.ArticleComments
</li>
<li>
<i class="fa fa-eye"></i>
@item.ArticleViews
</li>
</ul>
</div>
<div class="col-md-8 padding-left-0">
<h6 class="margin-top-0"> <span style="font-size:large">@item.Title</span><br><small class="font-xs"><i>Published by <a href="@Url.Action("GetProfileData","UserProfile", new { userid = item.fkiUserId })">@item.User_FullName</a></i></small></h6>
<p>
@Html.Raw(item.Description)
</p>
@*<a class="btn btn-danger" href="@Url.Action("ShowArticleDetails", "ILearn", new { id = item.KnowledgeSharingArticlesId })">Read more</a>*@
<button type="button" onclick="showArticle('@item.KnowledgeSharingArticlesId')" class="btn btn-danger" data-target="#show-details-modal" data-toggle="modal">
Read more
</button>
</div>
</div>
<hr>
}
}
</div>
}
}
}
<!--Loading Panel-->
<div id="loadingPanel" style="display: none;">
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-info" style="width: 100%">...LOADING...</div>
</div>
</div>
<!-- Show details modal-->
<div id="show-details-modal" class="modal fade" style="width:100%">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title"></h4>
<div id="loadingPanelShowDetails" class="col-md-12 text-center" style="display: none;">
<br />
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-info" style="width: 100%">...LOADING...</div>
</div>
</div>
<div id="target-show-details">
</div>
</div>
</div>
</div>
</div>
function showArticle(id) {
$("#target-show-details").html('');
$('#loadingPanelShowDetails').show();
$.ajax({
type: 'get',
url: '@Url.Action("ShowArticleDetails", "ILearn")',
contentType: 'application/json; charset=utf-8',
dataType: 'html',
data: { "id": id },
success: function (result) {
$("#target-show-details").html(result);
$('#loadingPanelShowDetails').hide();
var saveComment = function (data) {
$(data.pings).each(function (index, id) {
var user = usersArray.filter(function (user) { return user.id == id })[0];
alert(user.fullname);
data.content = data.content.replace('@@' + id, '@@' + user.fullname);
});
return data;
}
$('#articlecomments-container').comments({
profilePictureURL: 'https://viima-app.s3.amazonaws.com/media/public/defaults/user-icon.png',
currentUserId: 1,
roundProfilePictures: true,
textareaRows: 1,
enableAttachments: true,
enableHashtags: true,
enablePinging: true,
getUsers: function (success, error) {
$.ajax({
type: 'get',
traditional: true,
url: '@Url.Action("GetPinnedUsers", "ILearn")',
success: function (usersArray) {
success(usersArray)
},
error: error
});
},
getComments: function (success, error) {
$.ajax({
type: 'get',
traditional: true,
data: { "id": id },
url: '@Url.Action("GetArticleComments", "ILearn")',
success: function (commentsArray) {
success(saveComment(commentsArray))
},
error: error
});
},
postComment: function (data, success, error) {
$.ajax({
type: 'post',
dataType: "json",
url: '@Url.Action("PostArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (comment) {
success(comment);
},
error: error
});
},
putComment: function (data, success, error) {
$.ajax({
type: 'post',
dataType: "json",
url: '@Url.Action("PutArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (comment) {
success(comment);
},
error: error
});
},
deleteComment: function (data, success, error) {
$.SmartMessageBox({
title: "Deleting Comment?",
content: "Are you sure that you want to delete this comment?",
buttons: '[No][Yes]'
}, function (ButtonPressed) {
if (ButtonPressed === "Yes") {
$.ajax({
type: 'post',
dataType: "json",
url: '@Url.Action("DeleteArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function (data) {
if (data.status === "usersuccess") {
$.smallBox({
title: "<strong>Comment Deleted</strong>",
content: "<i class='fa fa-clock-o'></i> <i>Comment was successfully deleted! <strong</strong></i>",
color: "#659265",
iconSmall: "fa fa-check fa-2x fadeInRight animated",
timeout: 4000
});
success();
} else {
success();
}
}
});
}
if (ButtonPressed === "No") {
$.smallBox({
title: "<strong>Comment not deleted</strong>",
content: "<i class='fa fa-clock-o'></i> <i>This comment has not been deleted.</i>",
color: "#C46A69",
iconSmall: "fa fa-times fa-2x fadeInRight animated",
timeout: 4000
});
}
});
e.preventDefault();
},
upvoteComment: function (data, success, error) {
if (data.user_has_upvoted) {
$.ajax({
type: 'post',
dataType: "json",
url: '@Url.Action("UpVoteArticleComment", "ILearn")',
data: { "CVM": data, "articleId": id },
success: function () {
success(data)
},
error: error
});
} else {
$.ajax({
type: 'post',
url: '@Url.Action("DeleteArticleCommentUpvote", "ILearn")',
data: { "commentId": data.id },
success: function () {
success(commentJSON)
},
error: error
});
}
},
uploadAttachments: function (commentArray, success, error) {
var responses = 0;
var successfulUploads = [];
var serverResponded = function () {
responses++;
// Check if all requests have finished
if (responses == commentArray.length) {
// Case: all failed
if (successfulUploads.length == 0) {
error();
// Case: some succeeded
} else {
success(successfulUploads)
}
}
}
$(commentArray).each(function (index, commentJSON) {
// Create form data
var formData = new FormData();
$(Object.keys(commentJSON)).each(function (index, key) {
var value = commentJSON[key];
if (value) formData.append(key, value);
});
formData.append('fkiKnowledgeSharingArticlesId', id);
$.ajax({
url: '@Url.Action("UploadToArticleComments", "ILearn")',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (commentJSON) {
successfulUploads.push(commentJSON);
serverResponded();
},
error: function (data) {
serverResponded();
},
});
});
}
});
},
error: function (xhr, textStatus, errorThrown) {
alert(xhr.responseText);
}
});
}
部分视图的底部是该div的填充位置:
@model Innovation_Cafe.Models.KnowledgeSharingArticles
<div class="col-lg-12">
<div class="margin-top-10">
<div style="text-align:center;border:solid;border-style:solid">
<img src="@Model.ArticleImage" class="img-responsive" alt="img" style="width:100%;">
</div>
<ul class="list-inline padding-10">
<li>
<i class="fa fa-calendar"></i>
@Model.DateTimeStamp.ToLongDateString()
</li>
<li>
<i class="fa fa-comments"></i>
@Model.ArticleComments
</li>
<li>
<i class="fa fa-eye"></i>
@Model.ArticleViews
</li>
</ul>
</div>
</div>
<div class="col-lg-12">
<h6 class="margin-top-0"> @Model.Title<br><small class="font-xs"><i>Published by <a href="@Url.Action(" GetProfileData","UserProfile", new { userid=Model.fkiUserId })">@Model.User_FullName</a></i></small></h6>
<br />
<p>
@Html.Raw(Model.Description)
</p>
<p>
@if (Model.FileType == ".mp4")
{
<div style="text-align:center;border-style:solid">
<video controls width="100%">
<source src="@Model.FilePath" type="video/mp4" />
</video>
</div>
}
else
{
if (Model.FilePath !=null)
{
<p>Click here to view file: <a href="@Model.FilePath" target="_blank">Click here</a></p>
}
}
</div>
<div class="col-md-12">
<p> </p>
<hr style="border:solid" />
</div>
<div class="row col-md-12">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
在花费大量时间运行<div class="row col-md-12">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
文件之后,我发现在这里显示ping用户的情况:
jquery-comments.js
这似乎占用了View的css('top'),这会导致在部分视图上对用户执行ping操作。
答案 0 :(得分:2)
问题的发生,而不是因为错误的引导程序布局:您必须将所有col
包含在row
中,而在您的示例中,您使用raw
和col-md-12
相同的容器。
在我将列正确地包含在row
元素中之后,一切都以正确的方式开始工作。换句话说,就是这样写最后一部分:
<div class="row">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
请看一下Bootstrap 4中nesting的示例。
更新
由于您的提示在页面上绘制了许多文章,我设法重现了该错误。这个问题确实是由于滚动引起的,尽管在jquery.textcomplete.js
函数_fitToBottom
中的原因似乎更深(它考虑了主窗口滚动,而不考虑了嵌入式模式容器)。但是,我使用了一种更快的方法来代替更详尽的逻辑,而这恰恰是您所指向的位置(而不是所显示的最后两行):
var topPoint = self.options.scrollContainer[0].offsetTop;
var scrolledWindow = self.options.scrollContainer.parents().filter(function () {
return this.scrollTop > 0;
})[0];
var spaceAvailable = $(window).height() - (topPoint - scrolledWindow.scrollTop);
var elHeight = this.$el.height();
this.$el.css('top', spaceAvailable > elHeight ? topPoint: topPoint - elHeight);
该逻辑基于使用滚动查找最接近的父级,然后它测量剩余空间是否足以渲染下拉列表以找出其最终位置。它可能会略微遗漏指针,但是尽管进行滚动仍然可以正常工作。我已经在Chrome和Firefox中进行了尝试。希望它将引导您采用自己的方法。