I have a chatting room with maximum of 2 users, when one user send a message to another, the second user should be notified that new message is received just like Facebook
I have done it with Ajax request like
$(document).ready(
function() {
setInterval(function() {
$.ajax({
url: 'incs/check_new_msg.php' ,
cache: false,
success: function(data)
{
$('#message').html(data);
},
});
}, 1000);
});
<div id="message"></div>
In check_new_msg.php I use the following code:
$new_msg = mysql_query("select * from inbox where status = '0' ");
echo mysql_num_rows($new_msg);
The above code work good but the problem is that it check inbox and new message each second , but it seems harmful for processor as it run a MySQL query each second, please help me how to to execute checking query only when a new message is received.
i will give you a concept then you should try to implement it.
create an external text file when inserting something from another computer and at client side check same file each second rather than checking database. if file exists then check database else continue checking text file
So your only concern is it runs the query every second right?
Here's my solution:
$(document).ready(
function() {
function check_message()
{
$.ajax({
url: 'incs/check_new_msg.php' ,
cache: false,
success: function(data)
{
$('#message').html(data);
},
complete: function(data)
{
check_message();
},
});
}
check_message();
});
<div id="message"></div>
What this does is it will call the ajax recursively once the last ajax request is completed.
One of the ways of implementing the feature you discussed is long polling method. In this method you leave the connection open for certain time and if the changes occur within that time, the response is returned back to user. and another connection is opened and so on.
You should google about longpolling as there are lots of tutorials available. Best of luck
I found a good solution for this problem , for this purpose i use a notepad file in same directory where the script exists.
when inserting a new record from any computer you have to create notepad file with insertion.
$insert = mysql_query("insert into inbox .....");
if(insert)
{
if(!file_exists(notepad_file_path))
{
fopen(notepad_file_path);
}
}
Then I call ajax request request
$(document).ready(
function() {
function check_message()
{
$.ajax({
url: 'incs/check_new_msg.php' ,
cache: false,
success: function(data)
{
$('#message').html(data);
},
complete: function(data)
{
check_message();
},
});
}
check_message();
});
<div id="message"></div>
After that in external ajax file check existence of notepad file, if file exists then give access to database, in that way it will not be harmful for processor.
if(file_exists(notepad_file_path))
{
$new_msg = mysql_query("select * from inbox where status = '0' ");
echo mysql_num_rows($new_msg);
if(mysql_num_rows($new_msg) == 0)
{
unlink(notepad_file_path);
}
}
Related
I'd like to create a group chat, and would like all the messages and there matching usernames to be stored in a JSON file.
However, this looks quite hard to do without using node.js or MySQLi.
As you can see below, i can already read the JSON and display it in "chat-wrap". The problem is to add messages to the json file with PHP and/or AJAX, and update the HTML automatically.
The input is where the user types the message, and I assume i'll have to use JS to notice when ENTER is pressed, because i do not want to use a form (unless you can convince me otherwise).
My HTML:
<div class="col chat">
<div class="messages" id="chat-wrap">
<?php include "chat/chat_process.php"; ?>
</div>
<input maxlength='100' type="search" name="type_message" id="type_message" placeholder="Type a message...">
</div>
JSON example:
{
"message_list": [{
"uname": "User 1",
"text": "Hello everyone!"
},
{
"uname": "User 2",
"text": "Hey!"
},
{
"uname": "User 1",
"text": "Hello!"
}
]
}
I've already tried messing with the following code, but i'm new to JS and AJAX so ofcourse the code below didn't really work out...
$("#type_message").keypress(function (event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == '13') {
var msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
var name = 'Username';
var data = {
uname: name,
text: msg
};
$.ajax({
type: "POST",
url: "chat.php",
data: {
data: JSON.stringify(data)
},
dataType: "json",
success: function (response) {
// display chat data stored in text file
}
});
}
});
When a message is typed and entered, it should add to the JSON file and display it live on every users screen.
Please excuse me if i forgot to clarify anything, i'm kinda new to stackoverflow and i'm not sure what y'all pros expect to know...
Thanks!
I added a bit of code to your success function as a result you should be able to add the new text dynamically to your html and also saves the changes to your file messages.json.
$("#type_message").keypress(function(event) {
let keycode = event.keyCode ? event.keyCode : event.which;
if (keycode == "13") {
let msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
let name = "Username";
let data = {
uname: name,
text: msg
};
currentjson.push(data); // Also added one global variable which allows you to push the new data into the old json array.
$.ajax({
type: "POST",
url: "chat/chat.php", // I changed the url slightly since i put the php files in another directory
data: {
data: JSON.stringify(currentjson)
},
dataType: "json",
success: function(response) {
$(".chat").html(""); // Reset the html of the chat
addNodes(response); // Add the new Data to the chat by calling addNodesfunction
},
error: function(err) {
console.log(err);
}
});
}
Here is the php file that saves the json :
<?php
$file = fopen('messages.json','w');
$data = $_POST['data'];
fwrite($file,$data);
fclose($file);
echo $data; // return the new data set
addNodes function :
function addNodes(messages) {
for (let message of messages) {
const chatDiv = $(".chat");
const user = document.createElement("h3");
const content = document.createElement("p");
user.textContent = message.uname;
content.textContent = message.text;
chatDiv.append(user);
chatDiv.append(content);
}
}
I also changed your json to make it a little easier to loop through : (json example)
[
{ "uname": "User 1", "text": "Hello everyone!" },
{ "uname": "User 2", "text": "Hey!" },
{ "uname": "User 1", "text": "Hello!" }
]
Finally the whole client.js code looks like this :
$(document).ready(() => {
let currentjson = undefined;
$.ajax("chat/chat_process.php", { // This gets the file the first time the user opens the page
success: function(data) {
const messages = JSON.parse(data);
currentjson = messages;
addNodes(currentjson);
},
error: function() {
alert("There was some error performing the AJAX call!");
}
});
$("#type_message").keypress(function(event) {
let keycode = event.keyCode ? event.keyCode : event.which;
if (keycode == "13") {
let msg = $("#type_message").val();
if (msg.length == 0) {
alert("Enter a message first!");
return;
}
let name = "Username";
let data = {
uname: name,
text: msg
};
currentjson.push(data); // Also added one global variable which allows you to push the new data into the old json array.
$.ajax({
type: "POST",
url: "chat/chat.php",
data: {
data: JSON.stringify(currentjson)
},
dataType: "json",
success: function(response) {
$(".chat").html(""); // Reset the html of the chat
addNodes(response); // Add the new Data to the chat by calling addNodesfunction
},
error: function(err) {
console.log(err);
}
});
}
});
});
function addNodes(values) {
for (let message of values) {
const chatDiv = $(".chat");
const user = document.createElement("h3");
const content = document.createElement("p");
user.textContent = message.uname;
content.textContent = message.text;
chatDiv.append(user);
chatDiv.append(content);
}
}
But the final tasks that remains is that to display the new data to all the users currently using the website. To be able to do that i think you can use setInterval for like every 5 seconds and call a function which will detect if messages.json was changed by any user and then updates accordingly.
I hope my answers was useful :)
I believe you can, if you register the data into a variable or a text file in the server side.
You can trigger actions using server-sent events
https://www.w3schools.com/html/html5_serversentevents.asp
PS: someone has done it here:
https://www.developphp.com/video/JavaScript/Server-Sent-Events-Simple-Chat-Application-Example
Update sessions for chat directly
Advantages: It's much faster than passing files, storing information in DB. It's far less resource intensive. It avoids a lot of middle-man systems for handling the chat. It doesn't leave you holding onto increasing amounts of data. It avoids a LOT of legal issues with holding onto user data (because you aren't).
Disadvantages: You -have- to make sure it's secure in some way that best fits your use case. Also, troubleshooting session switching if something goes wrong can sometimes be a pain in the arse. Not useful if you're wanting to sell user data.
In php, store the information in session data. Then, fire off a child process (unconnected with the current session) that loads the session of the other user, and updates the other user's session data, having each session holding a variable in their session that stores the session IDs of the other users in the chat.
Mychat.php
$message = "" // Whatever's said
$groupids = implode(",", $other_users_ids); //Whatever your group's ids are.
$_SESSION["group_chat_users"]["my_id"] = session_id();
$_SESSION["my_chat_log"][]= $message;
exec("php my_group_update.php $groupids $_SESSION["group_chat_users"]["my_id"] $message");
my_group_update.php
$groupids = explode(",", $argv[1]);
$calling_user = $argv[2];
$message = $argv[3];
foreach ($groupids as $userid){
session_start($userid);
$_SESSION["my_chat_log"][]= $message");
}
As for outputing the JSON, it's as simple as:
fetch_log.php
header('Content-Type: application/json');
echo json_encode($_SESSION["my_chat_log"]);
Letting the user have their JSON log without it ever having to touch your Harddrive (or, alternatively, you can write it to your harddrive if you prefer.)
Notice: As should go without saying (but apparently needs to be said) As always, validate your inputs. Not doing so will leave you vulnerable to injection.
Ways suggestions on ways to prevent injection:
Have $message be a temporary file name written in Mychat.php and pulled in my_group_update.php
Convert $message to a hex string in Mychat.php and converted back in my_group_update.php
Alter my_group_update to pull the message from the first user's Session before switching to other users where it gets pasted.
Alert mychat to not include any variables other than the group_id in the exec call. Then have my_group_update just take the group ID, and cycle through all the shared chat session arrays, and find all new values, and update all the chats with it <---(probably the best).
Spin up a temporary very tiny VM that only handles the 1 chat, (maybe running with alpine linux or similar for a very small size that then self-destructs when the chat finishes.) This would be much higher overhead, but way more secure than anything else you'll even consider doing.
The list goes on.
I am trying to validate list of dynamic text fields.
Validation needs an AJAX call to interact with server.
At the backend I have written just one php file that reads the input request data and performs operation. Below is the example.
abc.js
row_count = 6
for (i = 1; i <=row_count; i++) {
id = "#val"+i.toString() ;
$(id).change(function(){
input_val="random";
$.ajax({
url:"url.php",
type:post,
async:true,
dataType: 'json',
data : {temp:input_val},
success:function(result){},
error: function (request, status, error) {}
});
});
}
url.php
<?php
$random_val = $_POST['temp'];
$cmd = 'systemcommand '.$random_val;
$flag = exec($cmd);
if ($flag == 0){
echo json_encode(array("status"=>'Fail'));
}
else{
echo json_encode(array("status"=>'Success'));
}
?>
It works fine when the row_count = 1 (Just one text field) but fails when the input is more than 1.
When the count is more than 1, the php script is not able to read the request data(The key in JSON data "temp"). it is blank in that case.
Any lead or help should be appreciated.
Thanks
Your javascript bit needs some adjusting, because you do not need to define an ajax for every single element. Use events based on a class. Also, since input behave differently than select, you should setup two different event class handlers.
function validateAjax ( element ) {
var input_val = element.val();// get the value of the element firing this off
$.ajax({
url: "url.php",
type: 'post',
async: true,
dataType: 'json',
data : { temp: input_val },
success: function(result) {
// check your result.status here
},
error: function (request, status, error) { }
});
}
$(".validate_change").on("change",function() { // for selects
validateAjax( $(this) );
});
$(".validate_input").on("input",function() { // for text inputs
validateAjax( $(this) );
});
And for your select or input you add that appropriate class.
<select class="validate_change" name="whatever"><options/></select>
<input class="validate_input" name="blah">
PS
I really worry about this code you have:
$cmd = 'systemcommand '.$random_val;
$flag = exec($cmd);
So, you are just executing anything that is coming in from a webpage POST var??? Please say this website will be under trusted high security access, and only people using it are trusted authenticated users :-)
I have the following Jquery code that listens to a user typing in a captcha and sends an ajax request on each keyup to see if the correct code has been typed:
$('#joinCaptchaTextBox').keyup(function() {
$.get('scripts/ajax/script.php', {
'join_captcha': '1',
'captcha': $('#joinCaptchaTextBox').val()},
function(data) {
var obj = JSON.parse(data);
if(obj.ajaxResponse.status) {
$('#joinCaptchaNotAcceptable').hide();
$('#joinCaptchaAcceptable').show();
}else{
$('#joinCaptchaAcceptable').hide();
$('#joinCaptchaNotAcceptable').show();
}
});
});
The PHP script on the other end just checks the session and replies:
if($siteCaptcha == $_SESSION['secretword']) {
$this->captchaCompare = TRUE;
}else{
$this->captchaCompare = FALSE;
}
This works fine 95% of the time but I'm finding sometimes it reports the captcha typed is incorrect even though its correct. I think this could be because when typed fast many requests are sent to the server and the order or requests coming back isn't the order sent and therefore (as only one will be correct) a prior one is recieved last and incorrect is displayed.
Is there a better way to do this? Is there a way to ensure the last request sent is recieved last? Is there something I'm missing here. I can give more info.
thankyou
Add a timeout so as to not send a request on every keyup when the user types fast:
$('#joinCaptchaTextBox').on('keyup', function() {
clearTimeout( $(this).data('timer') );
$(this).data('timer',
setTimeout(function() {
var data = {
join_captcha: '1',
captcha : $('#joinCaptchaTextBox').val()
};
$.ajax({
url : 'scripts/ajax/script.php',
data: data,
dataType: 'json'
}).done(function(result) {
$('#joinCaptchaNotAcceptable').toggle(!result.ajaxResponse.status);
$('#joinCaptchaAcceptable').toggle(result.ajaxResponse.status);
});
},500)
);
});
I need to load only new data into my div with ajax. At the moment I'm currently loading all data, because if I delete a record in the database it also removes it from my chat div.
Here is my js code:
var chat = {}
chat.fetchMessages = function () {
$.ajax({
url: '/ajax/client.php',
type: 'post',
data: { method: 'fetch', thread: thread},
success: function(data) {
$('.chat_window').html(data);
}
});
}
chat.throwMessage = function (message) {
if ($.trim(message).length != 0) {
$.ajax({
url: '/ajax/client.php',
type: 'post',
data: { method: 'throw', message: message, thread: thread},
success: function(data) {
chat.fetchMessages();
chat.entry.val('');
}
});
}
}
chat.entry = $('.entry');
chat.entry.bind('keydown', function(e) {
if(e.keyCode == 13) {
if($(this).val() == ''){
} else {
chat.throwMessage($(this).val());
e.preventDefault();
}
}
});
chat.interval = setInterval(chat.fetchMessages, 8000);
chat.fetchMessages();
I have had a look around and some say that if you pass a timestamp to the server and load new content that way, but I can't seem to get my head around that. If you need php let me know.
Right, so the timestamp thing makes the most sense. You'll need to do a few things:
On the back end, you need to make client.php accept a timestamp parameter in the querystring. When returning data, instead of just returning all of it, make it return everything since the time stamp, if given. Otherwise return everything.
The very first time you load the chat client, the first thing you should do is make an Ajax call to a new PHP file that returns the current server timestamp. Store the value of that in a Javascript variable as a Number.
During chat.fetchMessages(), increment the value of the timestamp variable by however long it's been since the last fetch (looks like 8000 milliseconds), and feed that to client.php, like url: '/ajax/client.php?timestamp=' + latestFetchTimestamp,
Instead of replacing all HTML content, append instead.
NOTE:
I gave up on trying to do the processing in one go, and just let it return after every x number of sends.
Two paths,
/sms?action=send
/sms?action=status
Let's say that the send path starts sending 10,000 sms messages via REST api calls.
I make a call to that page via ajax.
Then every few seconds, I make a call to /sms?action=status to see how the progress is going, and to update a progress bar.
The status path returns false if no messages are being sent.
What ends up happening is that the ajax call to the SEND path gets the ajax success: function called almost instantly, even though I know the script is taking 1+ minute to complete execution.
My progress bar never gets shown because the status ajax call (which is in a set interval with a few second delay) never seems to actually get called until the send call completes.
I'm trying to put the relevant code in here, but it may not be as clear as it should be without all the context.
<script type="text/javascript">
var smsInterval = 0;
var smsSending = false;
$(document).ready(function() {
var charCount = 0;
var smsText = "";
var smsTotal = <?php echo $options["smsTotal"]; ?>;
<?php if($options["sending"]): ?>
smsStatus();
smsSending = true;
smsInterval = setInterval("smsStatus()", 5000);
<?php endif; ?>
$("span#smsadmin_charcount").html(charCount.toString());
//send button
$("div#smssend").click(function() {
if(smsSending == true) {
return false;
}
smsStatus();
var dataString = $("#smsadmin_form").serialize();
smsSending = true;
$("div#smssend").html("Sending...");
$.ajax({
type: "POST",
url: "<?php echo $base_url; ?>/admin/sms",
data : dataString,
success: function(data) {
},
error: function(request, error) {
$("div.notice.sms").html("ERROR "+error+ "REQUEST "+request);
}
});
});
});
function smsStatus() {
var dataString = "smsaction=status&ajax=true";
$.ajax({
type: "POST",
url: "<?php echo $base_url; ?>/admin/sms",
data : dataString,
success: function(data) {
//data being false here indicates the process finished
if(data == false) {
clearInterval(smsInterval);
var basewidth = $("div.sms_progress_bg").width();
$("div.sms_progress_bar").width(parseInt(basewidth));
$("div.sms_progress_notice").html(parseInt(100) + "% Complete");
smsSending = false;
$("div#smssend").html("Send To <?php echo $options["smsTotal"]; ?> Recipients");
} else {
var pcomplete = parseFloat(data);
$("div.sms_progress_bg").show();
var basewidth = $("div.sms_progress_bg").width();
$("div.sms_progress_bar").width(parseInt(basewidth * pcomplete));
$("div.sms_progress_notice").html(parseInt(pcomplete * 100) + "% Complete");
}
},
error: function(request, error) {
$("div.notice.sms").html("ERROR "+error+ "REQUEST "+request);
}
});
}
I might be missing the point, but inside the $("div#smssend").click you got this line:
smsStatus();
shouldn't it be:
smsInterval = setInterval("smsStatus()", 5000);
and INSIDE the success: function(data) for /admin/sms ?
If the send part is sending out 10k messages, and the status returns true if currently sending a message, and false if in between sending, then you have a design issue.
For example, what is status supposed to be showing?
If status is to show how many of a certain block have been sent, then what you can do is to submit the message to be sent (or addresses), and get back some id for that block.
Then, when you ask for a status, pass the id, and your server can determine how many of that group has been sent, and return back the number that were successful, and unsuccessful, and how many are still pending. If you want to get fancy, you can also give an indication how much longer it may be before finishing, based on how many other requests are also pending.
But, how you approach this really depends on what you expect when you ask for the status.