Good day guys, can I combine load() and append() in JQuery/Ajax?
ex.
can I combine load() and prepend()? ex.
$('#notify').load(' #notify',function(){
$('#notification').prepend(`
<li>notif1</li>
<li>notif2</li>
`);
})
Updated:
The original code was like this.
function notif(){
$.ajax({
url: `/iaccs-hook-notifications`,
method: 'GET',
success: function(data){
console.log(data);
// if (data.success){
// $("#notify").load(" #notify");
// }
if (data.length > 0) {
//proceed
$('#btn-notif').addClass('js-has-new-notification');
$('#notif-list').append(`
<li>
<div class="an-info-single unread">
<a href="{{url('iaccs-hook-list')}}">
<span class="icon-container important">
<i class="icon-setting"></i>
</span>
<div class="info-content">
<h5 class="user-name">Update Client</h5>
<p class="content"><i class="icon-clock"></i>${data[0].created_at}</p>
</div>
</a>
</div>
</li>
`);
}
},
error: function(err){
swal('Error!','Please report this issue.', 'error');
}
});
}
$(document).ready(function(e) {
// let refreshNotification = () => {
// $('#notify').load(location.href + ' #notify');
// $(this).unwrap()
// }
notif();
var socket = io('http://www.iaccs-admin-console.test' + ':8080');
socket.on("message", function(message){
notif()
// $('.unread').on('click',function(){
// $.get('/markAsRead');
// });
});
});
and here is the view.
<div class="dropdown-menu" id="notify">
<p class="an-info-count">Notifications <span>{{count(auth()->user()->unreadNotifications)}}</span></p>
<div class="an-info-content notifications-info notifications-content">
<ul class="nav" id="notif-list">
</ul>
</div> <!-- end .AN-INFO-CONTENT -->
<div class="an-info-show-all-btn">
<a class="an-btn an-btn-transparent fluid rounded uppercase small-font" href="#">Show all</a>
</div>
</div>
The problem with the code above is that you need to refresh the page first for the whole drop down menu will notify the user and display the count of the notifications.
References
jquery comments
The jquery comments documentation
this issue in github
Attachments
comments-data.js is test data : Download here
jquery-comments.js creates the whole comments system: Download here
jquery-comments.min.js if you require it: Download here
Description
I have a view with a list of "articles" with a "read more" button on each "article" in the list. When I click on the read more button a modal opens up with a partial view with the jquery comments in it. However, when I search for the pinged users (using the # sign), the list of users don't show by the textarea, but instead higher up in the modal (far from the textarea).
Below is an image, then below that is my code. You will see at the bottom of the image I have put the '#' sign and the list of users is displayed on the top, it should be by the textarea. It also seems that when I click on the articles lower in the list, the higher the list of users display when I push the '#' sign:
MVC View
Below is the part populating the "Articles" from where the Modal is being called from:
#{
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>
Edit
</li>
<li class="divider"></li>
<li>
Delete
</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 #item.User_FullName</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>
}
}
}
Modal
This is placed at the top of the page(Under the #model appname.ViewModels.VM):
<!--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>
Jquery Code
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);
}
});
}
MVC Partial View
#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 #Model.User_FullName</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: Click here</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>
At the bottom of the partial view is this div where it is populated:
<div class="row col-md-12">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
EDIT
After spending quite some time running through the jquery-comments.js file, I found that displaying of the pinged users its happening here:
// CUSTOM CODE
// ========================================================================================================================================================================================
// Adjust vertical position
var top = parseInt(this.$el.css('top')) + self.options.scrollContainer.scrollTop();
this.$el.css('top', top);
This seems to be taking the css('top') of View, which causes the problem on the pinging of the users on the partialview.
The issue takes place rather because of your wrong bootstrap layout: you have to include all col into row, whereas in your example you use raw and col-md-12 for the same container.
After I included columns into row elements correctly everything started working the right way. In other words, just write the last section this way:
<div class="row">
<div class="col-md-12" id="articlecomments-container">
</div>
</div>
Please, take a look at an example of nesting in Bootstrap 4.
UPDATE
I've managed to reproduce the mistake thanks to your tip to draw numerous articles on the page. The issue is indeed because of scrolling, though the reason seems to be deeper in jquery.textcomplete.js in a function _fitToBottom (it takes into account the main window scroll but not of the embeded modal container). However, a faster approach I use instead of rectifying that elaborate peice of logic is exactly at the spot which you pointed to (instead of the last 2 rows you showed):
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);
The logic is based on looking for the closest parent with scroll and then it measures whether the rest of the space is enough to render the dropdown to figure out its final position. It might slightly miss the pointer, but still works fine in spite of scrolling. I've tried it out in Chrome and Firefox. Hopefully, it will lead you to your own approach.
I am having an issue with alpacajs form not submitting data from a textbox if the user does not tab off the textbox before clicking the submit button, if the user has 5 fields to fill out all but the last one is included in the json results.
<div class="panel-group" id="accordian" role="tablist">
<div class="panel-placeholder"></div>
</div>
<div>
<button class="btn btn-default" type="submit">Submit</button>
</div>
<script id="panel-template" type="text/x-handlebars-template">
{{#each panels}}
<div class="panel panel-primary">
<div class="panel-heading">
<h4 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#accordion" href="#{{panelId}}">
{{title}}
</a>
</h4>
</div>
<div id="{{panelId}}" class="panel-collapse collapse in">
<div class="panel-body">
{{#each sections}}
<div id={{formId}}></div>
{{/each}}
</div>
</div>
</div>
{{/each}}
</script>
and the js code
function onData(formData) {
var friendlyData = "";
// Grab the template script
var templateScript = $("#panel-template").html();
// Compile the template
var compiledTemplate = Handlebars.compile(templateScript);
var compiledHtml = compiledTemplate(formData);
// Add the compiled html to the page
$('.panel-placeholder').html(compiledHtml);
//submit all data
$("[type='submit']").click(function () {
var postData = {
data: JSON.stringify(formData),
friendlyData: friendlyData,
storeData: storeData,
origUrl: origUrl
}
$.ajax({
url: apiUrl + "submit/",
data: postData,
dataType: 'json',
type: 'POST',
success: function (data) {
alert("Data was saved");
},
error: function (err) {
alert(err.statusText);
}
});
});
}
Any help with this would be great, I have not been able to find a solution.
Thank you
I have the following html:
<div id="tabsuseradmin" class="tabui">
<ul>
<li>Add Users</li>
<li>Delete Users</li>
</ul>
<div id="tabs-1ua">
<div>
</div>
</div>
<div id="tabs-2ua">
<div>
</div>
</div>
</div>
and the following inside my js file document ready function:
$('.tabui').tabs({
activate: function (event, ui) {
$.ajax({
cache: false,
url: "/Session/Index/",
success: function (result) {
if (result.length == 0) {
window.location.href = '/Home/Index/'
}
}
});
}
});
$("#tabs-1ua").tabs({
activate: function (event, ui) {
alert("User add tab has been clicked.");
}
});
Above, you can see I am trying to specify behavior for all tab selections in general using the class tabui (this works fine) and also a specific behavior for an individual tab. This specific action does not work (the alert message does not appear and the breakpoint on the alert doesn't get hit). What should I do to fix it? Thank you.
Based on your comments, you want to do this:
https://jsfiddle.net/Twisty/eoa9tafm/
$(function() {
$('.tabui').tabs({
activate: function(event, ui) {
$.ajax({
cache: false,
url: "/Session/Index/",
success: function(result) {
if (result.length == 0) {
window.location.href = '/Home/Index/'
}
}
});
}
});
$("a[href='#tabs-1ua']").click(function(event, ui) {
alert("User add tab has been clicked.");
});
});
$("a[href='#tabs-1ua']").on('click', function() {
console.log("User tab clicked");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.0-rc.2/jquery-ui.min.js"></script>
<div id="tabsuseradmin" class="tabui">
<ul>
<li>Add Users</li>
<li>Delete Users</li>
</ul>
<div id="tabs-1ua">
<div>
</div>
</div>
<div id="tabs-2ua">
<div>
</div>
</div>
</div>
I have this button, and when clicked, it sends an ajax call which changes the value of score_up.
I dont see what the problem is. I tried firbug, but apparently it's not even detecting the javascript? :)) Thanks.
jquery:
$('.stats').delegate('.support', 'click', function(e) {
//stop event
e.preventDefault();
//get the id
var the_id = $(this).closest('.score').attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$(this).siblings("h2.score_up").html(msg).fadeIn();
//remove down button
// and remove support button
}
});
});
html:
<ul class="stats">
<li id="support_23"class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>
//vote down button
<li id="down_23"class="score">
<h2 class="score_down">12</h2>
<span style="text-align:center;">down</span>
</li>
<li>
<button type="submit" value="Actions" class="down" title="down">
<i></i>
<span>down</span>
</button>
</li>
</ul>
It is not valid HTML for a <button> to be a direct child of a <ul>.
Children of <ul> should be <li>. I wouldn't expect things to work properly with invalid HTML.
HTML with <button> inside a <li>:
<ul class="stats">
<li id="topic_23" class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i>
<span>Support</span>
</button>
</li>
</ul>
jQuery, fixing some of the traversal methods:
$('.stats').delegate('.support', 'click', function(e) {
//stop event
e.preventDefault();
// cache a reference to the previous <li> element
// since it is used more than once
var $prevLi = $(this).closest('li').prev('li');
//get the id
var the_id = $prevLi.attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$prevLi.find("h2.score_up").html(msg).fadeIn();
}
});
});
Your HTML is invalid, so I would do:
<form action="javascript:alert('form')";>
<ul class="stats">
<li id="topic_23"class="score">
<h2 class="score_up">12</h2>
<span style="text-align:center;">Supporters</span>
</li>
<li>
<button type="submit" value="Actions" class="support" title="support">
<i></i><span>Support</span></button>
</li>
</ul>
</form>
And then the jQuery (which in your original would not work, since you wanted .siblings() and not .closest() would now be:
var the_id = $(this).closest("li").siblings('.score').attr('id')
.split('_').pop();
and success:
$(this).closest("li").siblings("li.score").find("h2.score_up")
.html(msg).fadeIn();
I think you also run into troubles with prevent default, since you want to prevent default on the form, and in that case you might run into problems with delegate.
Here is what I would do with .live():
// Prevent form from submitting
$("form").live("submit", function(e) {
e.preventDefault(); });
// Run Ajax
$('button.support').live('click', function(e) {
//get the id
var $score = $(this).closest("li").siblings('.score'),
the_id = $score.attr('id').split('_').pop();
//the main ajax request
$.ajax({
context:this,
type: "POST",
data: "action=support&id=" + the_id,
url: "ajax/sa.php",
success: function (msg) {
$score.find("h2.score_up").html(msg).fadeIn();
}
});
});
Try it out on this jsFiddle