Jump to content

Help With Jquery $.each() And Json


chibineku

Recommended Posts

I am a little uncertain about the appropriate syntax for using $.each() in jQuery to interrogate JSON. Here is my script as it stands:

	 $.ajax({	 url: 'do_chat.php5',	 type: 'post',	 data: ({'message':text,'poster':poster,'logged_in':logged_in}),	 dataType: 'json',	 success: function(data) {	   $.each(data, function(entryIndex, entry) {	   if(entry['time'] > '10000000000000000') {	 $('#chatWindow').append(data);	   }	   });

This function sends the relevant data to 'do_chat.php5' and returns JSON, which looks like the following:{"poster":"","message":"No messages!","date":1256081631}I am not sure if that's what it's meant to look like, but my attempts to access the date have been unsuccessful, as is obvious from the fact that it constantly passes my greater-than-that-ludicrously-large-number test and stubbornly appends itself to my #chatWindow. I am not sure about the syntax for $.each, and if that is how it is used. I copied it from a book, but perhaps since I am only receiving one string I don't need it? I tried just data['time'] but that didn't work either... I'm kind of at sea on this one, and help would be great.

Link to comment
Share on other sites

First, it looks like you're supposed to use entry['date'] instead of entry['time']. Second, you're trying to compare a number with a string. If the timestamp is a number, compare it with another number (or else convert it to a number, then compare it with a number).

Link to comment
Share on other sites

Hm, you make good points. I corrected them. I still don't get anything. I simplified the test to simply check for the presence of message['time'] and it fails. Here is the new version, just in case there's anything else glaringly wrong:

	 $.ajax({	 url: 'do_chat.php5',	 type: 'post',	 data: ({'message':'','poster':poster,'logged_in':logged_in}),	 dataType: 'json',	 success: function(data) {	   $.each(data, function(interval, message) {	   if(message['time']) {	 $('#chatWindow').append(data);	   } });	 }	 });

Link to comment
Share on other sites

Hm, console.log(message) gets me:'No messages!'12**********Which is the appropriate message and the relevant timestamp. But accessing those is not happening. If I...oh, wait.Turns out data['time'] holds what I want...but I tried that! Now it works. Madness. Okay, awesome! I don't know what will happen with an array of messages, but with one it seems to work. Thanks, but don't go too far..

Link to comment
Share on other sites

Egads, I had written a big reply and then lost it. Is it possible to echo a stream of JSON objects? For example:while($message_data = mysqli_fetch_assoc($query_res)) {$message = array('poster' => $message_data['poster'],'message' => $message_data['message'],'time' => $message_data['time'])echo json_encode($message);}or do I need to create an array, and if so, is the following correct/appropriate?:$result = fetch_array($query, MYSQLI_BOTH);$message = array();for($i=0; $i < mysqli_num_rows($query), $i++) {$message['poster'] => $result['poster'],$message['message'] => $result['message'],$message['time'] => $result['time']}echo json_encode($message);And if that isn't, how do I create a JSON array of objects as opposed to a single object?

Link to comment
Share on other sites

You just create a multidimensional array. In Javascript it will show up as an array of objects.

$messages = array();while($message_data = mysqli_fetch_assoc($query_res)) {  $message = array(	'poster' => $message_data['poster'],	'message' => $message_data['message'],	'time' => $message_data['time']  );  $messages[] = $message;}echo json_encode($messages);

Link to comment
Share on other sites

Thanks. I have sort of avoided getting into multi dimensional arrays because I'm a simple guy. But, aksully, it is really simple. I think fetching more than the last record from my chat_buffer and estimating the lag will make for a smoother operation.

Link to comment
Share on other sites

I'm having a lot of problems now - like I said, I'm simple, and this is getting too complex. If I can impose, I would like to post the entire code and if anyone feels bored enough to give it a little read through, try to follow the logic and point out any glaring holes, I would be delighted for any insights. Here is it.chat.php5 - this page displays the chat window and jQuery starts recursive AJAX checks for new posts and currently online users, and attaches handlers to the send button and the return key to send a message. As soon as the page is opened, a variable is assigned to hold the time the user logged on - used later in determining which messages to show them. Additionally, a reset button calls a script via AJAX which kills the current session. If not session is set, the first little function fires because $_SESSION["poster"] = '', which leads to a call to users.php5. In that script if this session variable is not set, it sets it.

<?phpsession_start();?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head><meta http-equiv="Content-Type" content="text/html;charset=utf-8" /><script type="text/javascript" src="jquery-1.3.2.js"></script><script type="text/javascript"><?php include_once("db_include.php5");?>$(document).ready(function() {var logged_in = '<?php global $logged_in; $logged_in = time(); echo $logged_in; ?>';var check = '<?php echo $_SESSION["poster"];?>';if(check == '') {var poster = prompt("Please enter a username");$.post("do_chat.php5", {'poster':poster}, function(data){  window.location.href = window.location.href;  });}setTimeout(reload, 400);$('#send').click(function() {fetch_messages();});$('#message').bind("keypress", function(e) {  if(e.which == 13 || e.keycode == 13) {fetch_messages();  }});$('#new_user').click(function() {	 var poster = '<?php echo $_SESSION["poster"];?>';   $.post('reset.php5', {'poster':poster}, function(data) {	window.location.href = window.location.href;   });}); $('#message').focus();});function reload() {   var logged_in = '<?php echo $logged_in; ?>';   var poster = '<?php echo $_SESSION["poster"];?>';	 $.ajax({	 url: 'do_chat.php5',	 type: 'post',	 data: ({'message':'','poster':poster,'logged_in':logged_in}),	 dataType: 'json',	 success: function(data) {		 $.each(data, function() {					console.log(parseInt($('#chatWindow :last-child > span').html())+' '+data['time']);	   if((parseInt(data['time']) > parseInt($('#chatWindow :last-child > span').html()))) {	 $('#chatWindow').append('<div class="poster">server</div><div class="message"><span>'+data['time']+'</span>'+data['message']+'</div>');	   }	   });	 }	 });	$.post('users.php5', {'poster':poster}, function(data) { $('#users').html(data);});	setTimeout(reload, 2000);}function fetch_messages() { if($('#message').val()!='') {  var logged_in = '<?php echo $logged_in; ?>';  var text = $('#message').val();  var poster = '<?php echo $_SESSION["poster"];?>';	 $.ajax({	 url: 'do_chat.php5',	 type: 'post',	 data: ({'message':text,'poster':poster,'logged_in':logged_in}),	 dataType: 'json',	 success: function(data) {				$.each(data, function() {	   if((parseInt(data['time']) > parseInt($('#chatWindow :last-child > span').html()))) {				  console.log(parseInt($('#chatWindow :last-child > span').html())+' '+data['time']);	 $('#chatWindow').append('<div class="poster">server</div><div class="message"><span>'+data['time']+'</span>'+data['message']+'</div>');	   }	 });	 }	 });$('#message').val('');$.post('users.php5', {'poster':poster}, function(data) { $('#users').html(data);});}	 }</script><style type="text/css">//styles omitted for brevity</style><title>Chat App</title></head><body><div id="container"><div id="chatWindow"><div class="poster">test</div><div class="message"><span>0</span>test message</div></div><div id="users"></div></div><div id="input"><input type="text" name="message" id="message" maxlength="255" /><br /><input type="button" value="send" id="send" /><input type="button" value="new username" id="new_user" /></div></body></html>

Here is do_chat.php5. Briefly, this function receives any combination of three variables by POST: the current poster ($_SESSION["poster"]), a message if one is set, and the time the user logged in. If there is a message, it is written to the buffer table. If there are any messages newer than the user's logged in time, the last 10 are fetched. Then they are added to a multidimensional array, JSON encoded and returned to be parsed in chat.php5.

<?phpsession_start();include_once("db_include.php5");doDB(); if($_POST["message"]) {$message = check_chars_mailto($_POST["message"]);$poster = check_chars_mailto($_SESSION["poster"]);$sql = "INSERT INTO `buffer` (content, poster, time_added) VALUES ('$message', '$poster', now())";$res = mysqli_query($mysqli, $sql) or die(mysqli_error($mysqli));}$new = "SELECT * FROM (SELECT * FROM `buffer` WHERE time_added > ".$_POST["logged_in"]." ORDER BY time_added DESC LIMIT 10) AS temp_table ORDER BY time_added ASC";$new_res = mysqli_query($mysqli, $new) or die(mysqli_error($mysqli));if(mysqli_num_rows($new_res) > 0) {$messages = array();while($message_data = mysqli_fetch_assoc($query_res)) {  $message = array(	'poster' => $message_data['poster'],	'message' => $message_data['message'],	'time' => $message_data['time']  );  $messages[] = $message;}echo json_encode($messages);} else if(mysqli_num_rows($new_res) == 0) {$message = array(  'poster' => '',  'message' => 'No messages!',  'time' => 1);echo json_encode($message);}?>

users.php5 is called whenever the recursive reload function is, and it checks for users who are online. As explained before, if no session variable is set for the user, one is set and the user is written to the users table, or their last seen time updated.

<?phpsession_start();include_once("db_include.php5");doDB();if(!$_SESSION["poster"]) {$_SESSION["poster"] = $_POST["poster"];session_write_close();  }$update_user = "INSERT INTO chat_users (poster, last_seen) VALUES ( '".$_SESSION['poster']."', ".time().") ON DUPLICATE KEY UPDATE last_seen = ".time().""; $update_user_res = mysqli_query($mysqli, $update_user) or die(mysqli_error($mysqli));$users = "SELECT poster FROM chat_users";$users_res = mysqli_query($mysqli, $users) or die(mysqli_error($mysqli));if(mysqli_num_rows($users_res) == 0) {  echo "Online:<br />nobody";} else {  echo "Online<br /><ul>"; while($online = mysqli_fetch_assoc($users_res)) {  echo "<li>".$online['poster']."</li>"; } echo "</ul>";}$cleanup = "DELETE FROM chat_users WHERE last_seen < '".(time()-10)."'";$cleanup_res = mysqli_query($mysqli, $cleanup) or die(mysqli_error($mysqli));?>

And reset.php5 is simple:

<?phpsession_start();include_once("db_include.php5");doDB();$sql = "DELETE FROM chat_users WHERE poster = '".$_SESSION["poster"]."'";$res = mysqli_query($mysqli, $sql) or die(mysqli_error($mysqli));unset($_SESSION);session_destroy();?>

Because of the recursive nature of this app, it can be hard remembering what is going on. a few console.logs and watching the headers in Firebug really helps give an idea what's going on. The initial value of 0 held in the #chatWindow span is because one of the criteria for adding the new message I want to implement is that its timestamp must be greater than the last message displayed. However, if no messages are available, then do_chat.php5 returns a JSON object to that effect with a timestamp of 1. Each time there aren't any messages, it will compare the last span value and find it the same as that associated with no new messages. If there is a message, the real timestamp will be inserted and the next time the timestamp will either be the same or greater, leading to no action or a new message being appened, respectively. At the moment, the no new messages thing works fine, and you can see from the console logging that the 0 value is updated to one on the first do_chat call, and stays at one throughout. Because I am using $.each to iterate through the JSON array, you get the values displayed 3 times because there are three components to the array do_chat returns. Anyway, it's too much for my little brain. If anyone has the patience of a saint, here's a mini-hobby for you :)

Link to comment
Share on other sites

Okay, so I had made a few gaffes: I was inserting the messages with time_added as mysql's now() instead of PHP's time(), so I changed that. Now I can see the response in the console as [] but nothing more. So now the problem is how I'm parsing it, I guess.

Link to comment
Share on other sites

I vote we elect me class clown and make me sit in the corner til my nose is a right angle. I. Am. So. Dumb. kthnxbi.

Link to comment
Share on other sites

Just to let you know, justsomeguy, I finally figured out where I was going wrong and I have got JSON to work using the syntax you told me - so, thanks! It works better that way than the alternate solution which was to use the time of the last displayed message in the WHERE condition of the db query to check for new messages. That way led to duplicate (sometimes triplicate) messages if you sent a message too close to the time of the recursive checking function. Now I do the checking on the client side and compare the time of the next message to the time of the last one actually displayed - much better. No duplicates now. Cheers!

Link to comment
Share on other sites

Cool. But keep in mind that client-side timestamps aren't the same as server-side, the time on the server (PHP) will always be in the server's timezone and the time on the client (Javascript) will always be in the client's timezone.One easy way to do it might be to use IDs for each message. The client figures out what the last message ID was, and tells the server it wants messages newer than that.

Link to comment
Share on other sites

That's a good point - I expect nothing less. *opens ConTEXT...* Edit: the time I use is always a php timestamp, which may mitigate any mismatch, but it probably makes more sense shuffling around shorter ids than longer numbers.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...