Append the last message once - javascript

Hello guys i am trying to build a chat with Jquery , php , ajax and mysql
the problem that i am facing since few days is that when i get the value of the last message its keep getting append to the div what i want is to append the last message only once , and append again if there is a new message here is my ajax call
var chat = "";
$.ajax({
url: "php/gt_user.php",
type: "get",
success: function (result) {
var gtUser = $.parseJSON(result);
$.each(gtUser, function (idx, obj) {
var usrApp = "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrApp += "<p class='usr-name'>" + obj.Tables_in_chat + "</p></span>";
$('.userarea').append(usrApp);
}); // here i get all the username who sent a message and print them on a div
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
setInterval(function () {
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
var lastmsg = result;
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + lastmsg + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chat !== result) {
appedn();
} else {
chat = result;
}
}
});
}, 2000);
});
}
});
the respanse from php/admin_msg.php is working and i got the last message sucessfully the problem is that this script keep adding the same message to the message area , and what i want is to added the message only once if there is a new one

You need to somehow identify last message that is already appended to your html the best would be some id sent from server. So your message div should containt some data-id attribute, and then when you ask for next message get last children of $('.msgarea') element, read it data-id and compare with current one.
Another thing I would recommend to moving to some view library or framework, react, angular, vue or whatever. It gets complicated when you want to manage such features with pure jQuery.

i was finally able to fix the problem after 1 day of struggle so will post the answear here just in case it will help some one else facing the same issue
the part where i had to get all the username table from database i move it to my HTML and used a few line of php to echo the result like this(each user name has his own table)
// show all the user name that sent a message
$result = $con->query("show tables from chat");
while($row = mysqli_fetch_assoc($result)){
echo "<span><i class='fa fa-user-circle-o' aria-hidden='true'></i><p class='usr-name'>".$row['Tables_in_chat']."</p></span>";
}
then on my jquery script i moved the function that check for the last message every 2sec outside the click event so my Jquery script look more cleaner now
/* get the user name and added it to the header of the message box */
$('.userarea span').on('click', function () {
$('.msgarea').html("");
var usrName = $(this).text();
$('#usrname').text(usrName);
});
var chatdata = "";
/* check for new message and append the message area if there is a new one */
setInterval(function () {
var usrName = $('#usrname').text();
$.ajax({
url: "php/admin_msg.php",
type: "post",
data: {
name: usrName
},
success: function (result) {
function appedn() {
var usrMsg = "<div class='usr-msg'><i class='fa fa-user-circle-o' aria-hidden='true'></i>";
usrMsg += "<span><p>" + result + "</p></span></div>";
$('.msgarea').append(usrMsg);
}
if (chatdata !== result) {
appedn();
chatdata = result;
}
}
});
}, 2000);

Related

Ajax call won't navigate to a new view

I've created an application using codeigniter 3 that gets quizzes stored in the SQL database using a model and populate in the view using ajax and jquery.
Below is the code for populating data inside a div.
$(document).ready(function() {
$.ajax({
url: "/CW2/ASSWDCW2/cw2app/index.php/Leaderboard/quiz",
method: "GET",
dataType: "json"
}).done(function(data) {
$('#modtable tr').remove(); // clear table for new result
var quizzes = data.allQuizzes;
alert(quizzes.length);
var i;
for (i = 0; i < quizzes.length; i++) {
quiz = quizzes[i];
var block = ' <div id="quizMainBox"><h1>' + quiz.quizName + '</h1><br/><h3>' + quiz.creatorName + '<button onclick="myFunction(\''+quiz.quizId+'\')">Try it</button>'+'</h3></div>'
$('#allQuizBox').append(block);
}
});
return false;
// });
});
Below are 3 quizzes populated in the view.
What I want to do is when the user clicks on the "try it " button, I want the user to be directed to the "single_quiz_view" using the quiz id. So I wrote this ajax function (myFunction) below the above code.
function myFunction(quizId) {
// console.log("heyyyy");
// document.getElementById("demo").innerHTML = "Welcome"+quizId ;
$.ajax({
url: "/CW2/ASSWDCW2/cw2app/index.php/Quiz/loadQuiz/",
method: "POST",
}).done(function(data) {
alert("heyyy")
});
return false;
}
where Quiz is the controller name and loadQuiz is the function calling the "single_quiz_view"
//Quiz Controller
public function loadQuiz()
{
// $quizId = $this->uri->segment(3);
$this->load->view('quiz/single_quiz_view');
}
My problem is,
When I click on the "try it button", I get the alertBox inside the done function. I get the status code as 200 but still wont navigate to "single_quiz_view".Console wont give any errors.Please help

Reloading Ajax function with setTimeout doesnt clear previous timeout first

I am trying to load a chat box when a contact name is clicked. On initial load it displays the inbox. All functionality works ok until I try and click the contact name a second time. It loads the new contacts chat but also displays the original contact chat even though I set clearTimeout().
Here is the JS file -
$(document).ready(function(){
var contactTimeout;
var inboxTimeout;
function contact() {
var fromName = $('#from').val();
var toName = $("#to").val();
$(".chat-title").replaceWith("<div class='chat-title'>" + toName + "</div>");
$(".chat-form").fadeIn(100);
$.ajax('chat/get-chat.php', {
data: ({ to: toName,from: fromName}),
type: "POST",
success: function(data) {
$(".chat-body").replaceWith("<div class='chat-body'>" + data + "</div>");
contactTimeout = setTimeout(contact, 2000);
}
});
}
function inbox() {
var user = $('#from').val();
$.ajax('chat/get-chat-inbox.php', {
data: ({ user: user}),
type: "POST",
success: function(data) {
$(".chat-body").replaceWith("<div class='chat-body'>" + data + "</div>");
inboxTimeout = setTimeout(inbox, 2000);
}
});
}
// Load inbox when chat box is opened
$(".chat-arrow").click(function(){
clearTimeout(contactTimeout);
inbox();
});
// Load chat from contact name
$(".contact-name").click(function() {
clearTimeout(contactTimeout); // Here I try and kill previous timeout
clearTimeout(inboxTimeout);
var contactName = $(this).attr('id');
$("#to").val(contactName);
contact();
});
});
Why would it just add more timeout functions rather than replace them when a new contact name is clicked?
First i would suggest you instead of using replace each time, you could easily use .html(data) to put new data in existing content of chat-body.
And explanation is you call your function on ajax success (there's wait time to server respond to your request) and if you click in meanwhile on your another call, you will have two calls instead of one, because you can't clear timer that's not started yet.
Well one of the solutions would be, let timer works only through it's default state, and when you need some fast data, you can call your contact without calling the next timer.
$(document).ready(function(){
var contactTimeout;
var inboxTimeout;
/* add parameter which will mean will we call timer or not */
function contact(dotimer) {
var fromName = $('#from').val();
var toName = $("#to").val();
$(".chat-title").replaceWith("<div class='chat-title'>" + toName + "</div>");
$(".chat-form").fadeIn(100);
$.ajax('chat/get-chat.php', {
data: ({ to: toName,from: fromName}),
type: "POST",
success: function(data) {
$(".chat-body").replaceWith("<div class='chat-body'>" + data + "</div>");
/* default calling of timer with repeating */
if (dotimer) { contactTimeout = setTimeout(function(){ contact(true); }, 2000); }
}
});
}
function inbox() {
var user = $('#from').val();
$.ajax('chat/get-chat-inbox.php', {
data: ({ user: user}),
type: "POST",
success: function(data) {
$(".chat-body").replaceWith("<div class='chat-body'>" + data + "</div>");
inboxTimeout = setTimeout(inbox, 2000);
}
});
}
// Load inbox when chat box is opened
$(".chat-arrow").click(function(){
clearTimeout(contactTimeout);
inbox();
});
// Load chat from contact name
$(".contact-name").click(function() {
clearTimeout(inboxTimeout);
var contactName = $(this).attr('id');
$("#to").val(contactName);
/* call function without TIMER, default one will work as it works */
contact(false);
});
});

Ajax request does not update database until page refresh

I'm making a ToDo list for a dashboard system I'm creating.
So the idea is that a user can add new ToDo items, delete ToDo items and finish/unfinish ToDo items. I'm working in this project with codeIgniter.
The problem is when I'm adding a task it is added to the database but when I delete it after that or finish it, it has not been updated in the database. Only when I refresh the page and delete the task or finish the task after that it is updated in the database. I have checked the data and that has been succesfuly sended to the controller and from the controller to the model. It just does not get updated in the Database for some reason.
I'm sending all data using AJAX post requests to the codeigniter controller.
$(document).ready(function () {
runBind();
function runBind() {
/**
* Deletes a task in the To Do list
*/
$('.destroy').on('click', function (e) {
var $currentListItem = $(this).closest('li');
var $currentListItemLabel = $currentListItem.find('label');
$('#main-content').trigger('heightChange');
$.ajax({
url: 'dashboard/deleteToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text()
}).success(function (data) {
$currentListItem.remove();
}).error(function () {
alert("Error deleting this item. This item was not deleted, please try again.");
})
});
/**
* Finish the to do task or unfinish it depending on the data attribute.
*/
$('.toggle').on('ifClicked', function (e) {
console.log("hallo");
var $currentListItemLabel = $(this).closest('li').find('label');
/*
* Do this or add css and remove JS dynamic css.
*/
if ($currentListItemLabel.attr('data') == 'done') {
$.ajax({
url: 'dashboard/finishToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text() + '&finish=' + false
}).success(function (data) {
console.log(data);
$currentListItemLabel.attr('data', '');
$currentListItemLabel.css('text-decoration', 'none');
}).error(function () {
alert("Error updating this item. This item was not updated, please try again.");
})
}
else {
$.ajax({
url: 'dashboard/finishToDo',
type: 'post',
data: 'message=' + $currentListItemLabel.text() + '&finish=' + true
}).success(function (data) {
console.log(data);
$currentListItemLabel.attr('data', 'done');
$currentListItemLabel.css('text-decoration', 'line-through');
}).error(function () {
alert("Error updating this item. This item was not updated, please try again.");
})
}
});
}
$todoList = $('#todo-list');
/**
* Add a new To Do task.
*/
$("#frm_toDo").submit(function (e) {
e.preventDefault();
var url = $(this).attr('action');
var method = $(this).attr('method');
var data = $(this).serialize();
$.ajax({
url: url,
type: method,
data: data
}).success(function (data) {
addItemToHTMLList();
$('#new-todo').val('');
}).error(function () {
alert("Error saving this task. This task has not been saved, please try again.");
});
});
/**
* Adds the task that has been created directly to the HTML page
*/
var addItemToHTMLList = function () {
$('.destroy').off('click');
$('.toggle').off('click');
var todos = "";
todos +=
"<li>" +
"<div class='view'>" +
"<div class='row'>" +
"<div class='col-xs-1'>" +
"<input class='toggle' type='checkbox'>" +
"</div>" +
"<div class='col-xs-10'>" +
"<label id='item'>" + " " + $('#new-todo').val() + "</label>" +
"</div>" +
"<div class='col-xs-1'>" +
"<a class='destroy'></a>" +
"</div>" +
"</div>" +
"</div>" +
"</li>" + $todoList.html();
$todoList.html(todos);
$todoList.find('input').iCheck({checkboxClass: 'icheckbox_flat-grey', radioClass: 'iradio_flat-grey'});
runBind();
$('#main').show();
}
});
It would be great if you can help me out because I have no clue. I have checked all the data but it just does not get updated in the database before the page refresh.
Have you compared the XHR requests using browser dev tools to ensure they are 100% equivalent (for a delete on an existing todo versus a delete on a newly added todo)?
Also, the typical pattern is to use some sort of id instead of using the whole message as the matcher -- have you considered having finish/delete operate on the id of the todo instead of sending the text of the todo? You can make a unique id if you do not want to expose your database ids.
The problem is that you are creating objects after the page has finished initializing and the events have already been attached. You need to instead assign the events to a parent element, so that this element delegates the event to any new items in the to-do. See the "Delegated Events" section in the jQuery docs: http://api.jquery.com/on/

AJAX whenever I try to submit my text my div area duplicates the current data displayed plus my new data

Hi I have a working script of retrieving a JSON data result for my small chat application but my problem is that it displays a duplicate result of the text that was already posted plus my newly text that was inserted from my DB
here is my whole Javascript code:
function sendChatText() {
if (sendReq.readyState == 4 || sendReq.readyState == 0) {
sendReq.open("POST", 'includes/getChat.php?last=' + lastMessage, true);
sendReq.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
sendReq.onreadystatechange = AjaxRetrieve();
var param = 'message=' + document.getElementById('txtA').value;
param += '&name='+user;
param += '&uid='+uid;
param += '&rid='+document.getElementById('trg').value;
sendReq.send(param);
document.getElementById('txtA').value = '';
}
}
function AjaxRetrieve()
{
var rid = document.getElementById('trg').value,
data = {chat: uid, rid: rid, name: user};
$.ajax({
url: "includes/getChat.php",
type: "GET",
data: data,
dataType: 'json',
success: function(result){
$.each(result, function(rowKey, row) {
$("#clog").append($('<p />').html('<h4>'+ row.username +':</h4>' + row.message_content) );
});
}
});
}
I think your getChat.php returns all the chat text for that user, also you are appending them to #clog.
I have two suggestions
Return only the latest text from server by sending the time stamp from the JS itself like
data = {"chat": uid, "rid": rid, "name": user, "last_read_time": window.last_read_time};
window.last_read_time = new Date().format("d/M/yyyy hh:mm:ss tt"); //store new time
clear #clog before looping your data
$("#clog").empty(); //clear the previous msgs
$.each(result, function(rowKey, row) {
$("#clog").append($('<p />').html('<h4>'+ row.username +':</h4>' + row.message_content);
});

Upon querying a database, delete an item from a list obtained via getJSON

I have a list of items obtained upon querying a database. Result of the query is treated with jsonifyand finally obtained via getJson, by doing the following:
$(function() {
$.getJSON($SCRIPT_ROOT + '/appointments/', function(data) {
var output="<ul>";
for (var i in data.appts) {
output+="<li>" + data.appts[i].labo + "</li>"
}
output+="</ul>";
$("#result").html(output)
return false;
});
});
So far so good...
Now I need to give the possibility to delete each of the above listed items, by calling (for example ) the following Flaskfunction:
#app.route('/appointments/<int:appointment_id>/delete/', methods=['DELETE'])
def appointment_delete(appointment_id):
appt = db.session.query(Appointment).get(appointment_id)
db.session.delete(appt)
db.session.commit()
return jsonify({'status': 'OK'})
Unfortunately I have no clue on how it's possible to bridge these two pieces of code. Since I've being struggling on that for a while, I would appreciate any help that will allow me to get out of the mud... Thanks a lot.!
EDIT according to #dcodesmith's comment
The getJSON response:
{
"appts":[
{
"id":1,
"day":"Mardi",
"labo":"l1",
"modified":[
"21/01/2014"
],
"groups":"5",
"plage_h":"10h00",
"sem":"5",
"start":[
"28/01/2014"
]
},
{
"id":4,
"day":"Vendredi",
"labo":"l1",
"modified":[
"22/01/2014"
],
"groups":"5",
"plage_h":"10h00",
"sem":"5",
"start":[
"31/01/2014"
]
}
]
}
Changes required
Firstly, edit your output HTML to include an anchor tag which should have a data-id attribute with the appts id assigned to it.
Create a click event on the anchor tag in your list of appts
Code
$(function() {
$.getJSON($SCRIPT_ROOT + '/appointments/', function(data) {
var output = "<ul>";
for (var i in data.appts) {
var appt = data.appts[i];
output += "<li>" + appt.labo + "delete</li>"
}
output+="</ul>";
$("#result").html(output)
return false;
});
$(document).on('click', 'a.delete', deleteAppt);
function deleteAppt(e){
e.preventDefault();
var $this = $(this),
id = $this.data('id'),
url = "/appointments/" + id + "/delete/";
$.ajax({
url: url,
type: 'POST',
data: {id: id}
})
.done(function(data, textStatus, jqXHR){
if (data.status === 'OK'){
// if successful remove deleted row
$this.parent('li').remove();
}
})
.fail(function(jqXHR, textStatus, errorThrown){
//log your error here, if any is caught. This will be very helpful for debugging
})
}
});
Note: I know nothing about Flask, but this should work Ceteris Paribus

Categories