Chrome issue - chat lines return multiple times - javascript

I wrote a little chat plugin that i'll need to use on my site. It works with a simple structure in HTML, like this:
<div id="div_chat">
<ul id="ul_chat">
</ul>
</div>
<div id="div_inputchatline">
<input type="text" id="input_chatline" name="input_chatline" value="">
<span id="span_sendchatline">Send</span>
</div>
There's a 'click' bound event on that Span element, of course. Then, when the user inserts a message and clicks on the "Send" span element, there's a Javascript function with calls an Ajax event that inserts the message into the MySQL database:
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
function_get_newchatlines();
}
});
}
And, in case the message is successfully inserted into DB, it calls a function to read new lines and put them in HTML structure i posted before:
function function_get_newchatlines()
{
$.ajax
({
type: "POST",
url: "ajax-chat-loadnewlines.php", //1: ok, 0: errore
data: '',
dataType: "text",
cache: false,
success: function(ajax_result) //example of returned string: 'message1>+<message2>+<message3'
{
//explode new chat lines from returned string
var chat_rows = ajax_result.split('>+<');
for (id_row in chat_rows)
{
//insert row into html
$('#ul_chat').prepend('<li>' + chat_rows[id_row] + '</li>');
}
$('#span_sendchatline').html('Send');
}
});
}
Note: 'ajax_result' only contains html entities, not special chars, so even if a message contains '>+<', it is encoded by the php script called with Ajax, before being processed from this JS function.
Now, comes the strange behaviour: when posting new messages Opera, Firefox and even IE8 works well, as intended, like this:
But, when i open Chrome window, i see this:
As you can see, in Chrome the messages are shown multiple times (increasing the number each time, up to 8 lines per message). I checked the internal debug viewer and it doesn't seem that the "read new lines" function is called more than one time, so it should be something related to Jquery events, or something else.
Hope i've been clear in my explanation, should you need anything else, let me know :)
Thanks, Erenor.
EDIT
As pointed out by Shusl, i forgot to mention that the function function_get_newchatlines() is called, periodically, by a setInterval(function_get_newchatlines, 2000) into Javascript.
EDIT2
Here's is a strip of the code from the PHP file called by Ajax to get new chat lines (i don't think things like "session_start()" or mysql connection stuff are needed here)
//check if there's a value for "last_line", otherwise put current time (usually the first time a user logs into chat)
if (!isset($_SESSION['prove_chat']['time_last_line']) || !is_numeric($_SESSION['prove_chat']['time_last_line']) || ($_SESSION['prove_chat']['time_last_line'] <= 0))
{
$_SESSION['prove_chat']['time_last_line'] = microtime(true);
}
//get new chat lines
$result = mysql_query("select * from chat_module_lines where line_senttime > {$_SESSION['prove_chat']['time_last_line']} order by line_senttime asc; ", $conn['user']);
if(!$result || (mysql_num_rows($result) <= 0))
{
mysql_close($conn['user']); die('2-No new lines');
}
//php stuff to create the string
//....
die($string_with_chat_lines_to_be_used_into_Javascript);
Anyway, i think that, if the problem was this PHP script, i would get similar errors in other browsers, too :)
EDIT4
Here's the code that binds the click event to the "Send" span element:
$('#span_sendchatline').on('click', function()
{
//check if there's already a message being sent
if ($('#span_sendchatline').html() == 'Send')
{
//change html content of the span element (will be changed back to "send"
//when the Ajax request completes)
$('#span_sendchatline').html('Wait..');
//write new line
function_write_newchatline();
}
//else do nothing
});
(Thanks to f_puras for adding the missing tag :)

I would do one of the following:
option 1:
stop the timer just before the ajax call in function_write_newchatline() and start the timer when the ajax call returns.
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
stop_the_timer();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
function_get_newchatlines();
},
complete: function() {
start_the_timer();
}
});
}
option 2:
Not call function_get_newchatlines() at all in the success event of the ajax call. Let only the timer retrieve the chat entries.
function function_write_newchatline()
{
var chatline = $('#input_chatline').val();
$.ajax
({
type: "POST",
url: "ajax-chat-writenewline.php", //1: ok, 0: errore
data: ({'chat_line': chatline}),
dataType: "text",
cache: false,
success: function(ajax_result)
{
// do nothing
}
});
}
I think there is some race condition between the function_get_newchatlines() that is called after a chat entry is added by the user and the periodical call of function_get_newchatlines() by the timer.
option 3:
Use setTimeout instead of setInterval. setInterval can mess things up when the browser is busy. So in the end of the setTimeout function call setTimeout again.

Related

How to send multiple variables from a HTML web page to a python script without form submissions

This is going to be a strange one if I'm honest so please bare with me.
Im currently working on a project that requires me to call python scripts that are part of a webserver that is running a HTML webpage from the page itself i.e You move a slider on the webpage and it calls the python script and passes the value of the slider and an ID value that the script requires to pass the value to its relevant end point. In this case its a monitor ID and the slider value is the brightness value that the brightness must be set to.
Currently I have achieved this with a form submission action but I don't want the webpage to reset once a new value is sent and so JavaScript is my next best option using Ajax requests and while I have made some progress I am basically a noob with web development and have hit a brick wall.
Here is the script I have attempted and the python script that it calls.
<script>
slider.oninput = function (event, ui)
{
var slider_val=event.target.id;
console.log(slider_val);
$( "#"+slider_val ).val( ui.value );
$( "#amount_"+slider_val ).val( $( "#"+slider_val ).slider( "value" ) );
changeBrilliance();
}
function changeBrilliance(value, monid)
{
$.ajax({
type: "POST",
url: "/brilliancechange",
data: { mydata: value, mon: monid }
});
}
</script>
Python:
#app.route('/brilliancechange', methods=['POST'])
def brillchange():
userinput = request.form['mydata']
selectedMon = request.form['mon']
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
DATA = "A6" + selectedMon + "0000000401C0"
DATA += hex(int(userinput)).lstrip("0x")
check = checksum(bytes.fromhex(DATA))
DATA += hex(int(check)).lstrip("0x")
dataarray = hextobyte(DATA)
s.sendall(dataarray)
s.close()
What should the javascript look like if i want to call this method with a different ID and value each time without it reloading the webpage everytime?
It looks like changeBrilliance() accepts two parameters but when called nothing is getting passed. I'm not too familiar with the Python framework being used, but as long as it accepts content-type: application/json in POST body you could do:
// not totally sure which value/id combo you need but just pass the necessary ones here
changeBrilliance(slider_val, ui);
function changeBrilliance(value, monid)
{
var myObj = { 'myData': value, 'mon': monid };
$.ajax({
type: "POST",
url: "/brilliancechange",
contentType: "application/json",
data: JSON.stringify(myObj)
});
}
Then if you want something in the browser to change, you'll have to callback on done if successful or fail if something goes wrong, and always callback for some behavior that should always happen:
$.ajax({
type: "POST",
url: "/brilliancechange",
contentType: "application/json",
data: JSON.stringify(myObj)
}).done(function(data) {
// do something
}).fail(function(jqXHR, textStatus, err) {
// handle error
}).always(function(data) {
// always callback
});

Remember the state of clicked button with AJAX

I have different cards displayed on an app, the information is coming from the database in a loop. I have the option to put a 'redeem button' on cards if it's something a user can use just once. When the user clicks the redeem button, I get in the database the information (card name, clientID). Then, I made another AJAX call to get the information from the database and what I want is to check if the clientID and the carndame are already in the database then delete it just for that user. I don't wanna use localStorage or cookies because if the user delete the cookies they would see the card again and I don't want this to happen.
-- AJAX CALL TO POST --
$(`#promotion-container .promo${i} .redddButt`).click(function(e){
e.stopPropagation();
var esc = $.Event("keyup", { keyCode: 27 });
$(document).trigger(esc);
$('#deletePromo').on('click', function(){
if (eventName && customerID)
$(`#promotion-container .promo${i}`).remove() // this removes it but if you reload the page it appears again.
})
$('#just-claimed-popup2').addClass('reveal');
var theDiv = document.getElementById("card-just-claimed");
var content = document.createTextNode(eventName);
theDiv.appendChild(content);
$.ajax({
type: 'POST',
url: '/api/promotions_redemption',
crossDomain: true,
dataType: 'json',
data: {
eventName : eventName,
dateReedem : dateReedem,
}
});
})
--AJAX CALL TO GET INFO FROM DATABASE --
let success = function(res, eventName) {
let cardData = res['cardData'] //cardData is the info from database
for(i=0; i<cardData.length; i++){
let nameEvent = cardData[i]['event_name']
let customerID = cardData[i]['customer_id']
let clicked_button = cardData[i]['clicked_button']
let eventName1 = promotions['event_name'] // getting the names of all cards displayed
if(customerID && nameEvent == eventName1){
$(`#promotion-container .promo${i}`).remove(); // HERES THE PROBLEM
}
}
}
$.ajax({
type: 'GET',
url: '/api/promotions-check',
crossDomain: true,
dataType: 'json',
success: success,
});
The problem is that my conditional on my GET call is successful but it forgets the id of the card, meaning that when I try to console.log the id of the promo it comes as 0, instead of the actual number, so it's forgetting the information of the cards rendered and don't know what to delete.
What would be the best way to achieve the card to be deleted? Do I need to do it in the click event too? and if yes, can I have 2 Ajax calls in the same function?
If you change the approach you would be able to achieve this more easily. When you send a post request to delete the item or redeem the code in your case, upon success return same data and upon some condition just delete the item from DOM. On page load it shouldn't load whichever was redeemed.
I personally don't see a point of doing another GET to delete the code which was redeemed.
$.ajax({
type: 'POST',
url: '/api/promotions_redemption',
crossDomain: true,
dataType: 'json',
data: {
eventName : eventName,
dateReedem : dateReedem,
},
success: function(result){
//on success, ie when the item is deleted -> delete from the DOM.
}
});

Passing JSON through AJAX Plus Button Dilema

so I am attempting to pass some information in a JSON object and have a php page insert the data into a database. However, I am running into some trouble. The "update" button exists in a popup window. The user then clicks "update" and the inputted data should be processed accordingly. However, I fear that I am not even reaching my .click function. None of my alerts seems to be triggered. Below I will point out where issues are occurring. Thank you!
<script>
function updateTable()
{
document.getElementById("testLand").innerHTML = "Post Json";
//echo new table values for ID = x
}
$('#update').click( function() {
alert("help!");
var popupObj = {};
popupObj["Verified_By"] = $('#popupVBy').val();
popupObj["Date_Verified"] = $('#popupDV').val();
popupObj["Comments"] = $('#popupC').val();
popupObj["Notes"] = $('#popupN').val();
var popupString = JSON.stringify(popupObj);
alert(popupString);
#.ajax({
type: "POST",
dataType: "json",
url: "popupAjax.php",
//data: 'popUpString = '+ popupString,
data: popupObj,
cache: false,
success: function(data) {
updateTable();
alert("testing tests");
}
});
});
</script>
<html>
<button onClick="openPopup(<?php echo $row['ID'];?>);"><?php echo $row['ID'];?></button> <!--opens a popup with input options-->
<button id="update">Update</button> <!-- this button is supposed to cause the javascript above to run when clicked, however none of my alerts seem to be reached.-->
</html>
Thank you for looking!
1)I can only guess that you're trying to use JQUERY?
Where do you include the library?
2 )#.ajax isnt valid Jquery function
try $.ajax instead

How to return json value from php page to html page by ajax and how to show result on html page

I m validating email id in php and ajax, and want to return value from php page to html in JSON format.
I want to keep that return value in php variable for the further use.
I'm doing these all in codeigniter, and I want to show .gif image while my AJAX is processing. (Pre loader image)
AJAX/Javascript/jQuery:
function checkEmail(value_email_mobile) {
if (value_email_mobile !== '') {
//alert('te');
$.ajax({
type: "POST",
url: url_check_user_avail_status,
data: "value_email_mobile=" + value_email_mobile,
success: function(msg) {
alert(msg);
//$('#psid').html("<img src='images/spacer.gif'>");
// $('#stat').html(msg);
//
//$('#sid').sSelect({ddMaxHeight: '300px'});
},
error: function() {
//alert('some error has occured...');
},
start: function() {
//alert('ajax has been started...');
}
});
}
}
PHP/Controller:
<?php
function check_email_or_mobile($param)
{
$ci = CI();
$value = $param['email_or_mobile'];
$query = "SELECT user_email , mobile FROM tb_users WHERE user_email = '$value' or mobile = '$value'";
$query = $ci->db->query($query);
if ($query->num_rows() > 0)
{
if (is_numeric($value))
{
return $res = "This mobile number is not registerd";
}
else
{
return $res = "This Email id is not registerd";
}
}
}
This is just to give you an example on how it will work.
First off, (obviously) there must the a preloader image ready inside the document. This must be hidden initially.
Second, before triggering the AJAX request, show the loading animated GIF.
Third, after the request if successful. Hide the image again inside your success: block inside the $.ajax().
Consider this example: Sample Output
PHP:
function check_email_or_mobile($param) {
// your functions, processes, blah blah
// lets say your processes and functions takes time
// lets emulate the processing by using sleep :)
sleep(3); // THIS IS JUST AN EXAMPLE! If your processing really takes time
$data['message'] = 'Process finished!';
// with regarding to storing, use sessions $_SESSION for further use
$_SESSION['your_data'] = $data_that_you_got;
echo json_encode($data); // use this function
exit;
}
// just a simple trigger for that post request (only used in this example)
// you really dont need this since you will access it thru your url
// domain/controller/method
if(isset($_POST['request'])) {
check_email_or_mobile(1);
}
HTML/jQuery/AJAX:
<!-- your animated loading image -->
<img src="http://i600.photobucket.com/albums/tt82/ugmhemhe/preloader.gif" id="loader" style="display: none;" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- <script type="text/javascript" src="jquery.min.js"></script> -->
<script type="text/javascript">
$(document).ready(function(){
// before the request, show the GIF
$('#loader').show();
$.ajax({
url: document.URL, // JUST A SAMPLE (url_check_user_avail_status)
type: 'POST',
data: {request: true},
dataType: 'JSON',
// data: "value_email_mobile=" + value_email_mobile,
success: function(response) {
// After a succesful response, hide the GIF
$('#loader').fadeOut();
alert(response.message);
}
});
});
</script>
My assumption is, since this is just a simple email checking, this wont really take a chunk of time. The other way is to fake the loading process.
success: function(response) {
// After a succesful response, hide the GIF
// Fake the loading time, lets say 3 seconds
setInterval(function(){
$('#loader').fadeOut();
alert(response.message);
}, 3000);
}
Let us know what part of your code is not working?
1) Check if the request flow is hitting the function checkEmail? PHP has inbuilt JSON converting utility json_encode. You could start using that.
2) If you want to store this on the server for further use, you could think about usage like
a) Storing it in Database (If really needed based on your requirements. Note: This is always expensive)
b) Session - If you would want this info to be available for all the other users too.
c) Or keep it in the memory like any of the caching mechanisms like memcache etc
3) For displaying the busy display,
// Before the below ajax call, show the busy display
$.ajax({
});
// After the ajax call, hide the busy display.
You could do this using JavaScript / JQuery on your choice.
I remember using
JSON.parse(data)
to convert JSON ino a javascript object.
Jquery has its own JSON parser btw. Something like $.JSONParse(data)

How to bring ajax search onkeyup with jquery

My Script to call ajax
<script language="javascript">
function search_func(value)
{
$.ajax({
type: "GET",
url: "sample.php",
data: {'search_keyword' : value},
dataType: "text",
success: function(msg){
//Receiving the result of search here
}
});
}
</script>
HTML
<input type="text" name="sample_search" id="sample_search" onkeyup="search_func(this.value);">
Question: while onkeyup I am using ajax to fetch the result. Once ajax result delay increases problem occurs for me.
For Example
While typing t keyword I receive ajax result and while typing te I receive ajax result
when ajax time delay between two keyup sometime makes a serious issue.
When I type te fastly. ajax search for t keyword come late, when compare to te. I don't know how to handle this type of cases.
Result
While typing te keyword fastly due to ajax delays. result for t keyword comes.
I believe I had explained up to reader knowledge.
You should check if the value has changed over time:
var searchRequest = null;
$(function () {
var minlength = 3;
$("#sample_search").keyup(function () {
var that = this,
value = $(this).val();
if (value.length >= minlength ) {
if (searchRequest != null)
searchRequest.abort();
searchRequest = $.ajax({
type: "GET",
url: "sample.php",
data: {
'search_keyword' : value
},
dataType: "text",
success: function(msg){
//we need to check if the value is the same
if (value==$(that).val()) {
//Receiving the result of search here
}
}
});
}
});
});
EDIT:
The searchRequest variable was added to prevent multiple unnecessary requests to the server.
Keep hold of the XMLHttpRequest object that $.ajax() returns and then on the next keyup, call .abort(). That should kill the previous ajax request and let you do the new one.
var req = null;
function search_func(value)
{
if (req != null) req.abort();
req = $.ajax({
type: "GET",
url: "sample.php",
data: {'search_keyword' : value},
dataType: "text",
success: function(msg){
//Receiving the result of search here
}
});
}
Try using the jQuery UI autocomplete. Saves you from many low-level coding.
First i will suggest that making a ajax call on every keyup is not good (and this why u run in this problem) .
Second if you want to use keyup then show a loading image after input box to show user its still loading (use loading image like you get on adding comment)
Couple of pointers. Firstly, language is a deprecated attribute of javascript. In HTML(5) you can leave the attribute off, or use type="text/javascript". Secondly, you are using jQuery so why do you have an inline function call when you can do that with jQuery too?
$(function(){
// Document is ready
$("#sample_search").keyup(function()
{
$.ajax({
type: "GET",
url: "sample.php",
data: {'search_keyword' : value},
dataType: "text",
success: function(msg)
{
//Receiving the result of search here
}
});
});
});
I would suggest leaving a little delay between the keyup event and calling an ajax function. What you could do is use setTimeout to check that the user has finished typing before then calling your ajax function.

Categories