I've built a notification system, and its almost working. I just have one niggly bit that I can't seem to get my head around.
When a new update comes in from a friend it prints out the number of new notifications as expected, only if a user posts twice num_rows 2 pops up.. but if a user posts again it updates and replaces the 2 new notifications number back to 1 in the div because I'm using html in the ajax to replace.
So my question is, how can I update the div to get the total amount of results so it goes 1,2,3,4 etc instead of 2,1,1,1,1.
I don't want to replace the num of new rows with only the (1) update in the div, just add to the amount of new updates already inside it.
A bit like when facebook shows amount of notifications. say I have two and a friends posts on my wall I then will have 3.. but at the moment its adding the last new num row and going back to 1.
AJAX
<script type="text/javascript">
function loadIt() {
var notification_id="<?php echo $notification_id['notification_id'] ;?>"
var notification_id= window.localStorage.getItem ('lastId');
$.ajax({
type: "GET",
url: "viewajax.php?notification_id="+notification_id,
dataType:"json",
cache: false,
success: function(response){
if(response){
dataHandler;
if(response.num){
window.localStorage.setItem('lastId', response.notification_id);
var dataHandler = function(response){
var isDuplicate = false, storedData = window.localStorage.getItem ('lastId');
for (var i = 0; i < storedData.length; i++) {
if(storedData[i].indexOf(response) > -1){
isDuplicate = true;
}
}
if(!isDuplicate){
storedData.push(response);
}
};
if(response){
if(response.num){
$("#notif_actual_text-"+notification_id).prepend('<div id="notif_actual_text-'+response['notification_id']+'" class="notif_actual_text">'+response['notification_content']+' <br />'+response['notification_time']+'</div></nr>');
$("#mes").html(''+ response.num + '');
}
};
}
}
}
});
}
setInterval(loadIt, 10000);
PHP
$json = array();
$com=mysqli_query($mysqli,"select notification_id,notification_content,notification_time from notifications where notification_id > '$id' AND notification_status=1 ");
echo mysqli_error($mysqli);
$num = mysqli_num_rows($com);
if($num!=1){
$json['num'] = $num;
}else{
$json['num'] = 0;
}
$resultArr = mysqli_fetch_array($com);
$json['notification_id'] = $resultArr['notification_id'];
$json['notification_content'] = $resultArr['notification_content'];
mysqli_free_result($com);
header('Content-Type: application/json');
echo json_encode($json);
}
The number of notifications on client-side is storedData.length.
So i would replace the counter
$("#mes").html(''+ response.num + '');
with
$("#mes").html(storedData.length);
Related
I'm building an AJAX timeline of wall posts and I have the following function to check for new posts and then post the new ones to the wall, similar to how Twitter works:
wall_posts.php
$news = tz::shared()->news->getNew(25);
<div id="wall_posts">
<?php foreach ($news as $news_post) { ?>
<div class="wall_post"><?php echo $news_post['message']; ?></div>
<?php } ?>
</div>
jQuery:
function checkForNewPosts() {
// This represents the last record in the table AKA the "most recent" news
var lastCustomerNewsID = <?php echo $news[0]['id']; ?>;
$.ajax({
url: "example.com/ajax.php",
method: "post",
data:{
lastCustomerNewsID: lastCustomerNewsID,
},
dataType:"text",
success:function(data)
{
$('#wall_posts').prepend(data);
}
});
}
setInterval(checkForNewPosts, 10000);
The news PHP array above with index 0 indicates it is the last/most recent ID in the array/table
PHP (ajax.php):
if ($_POST) {
$lastCustomerNewsID = $_POST['lastCustomerNewsID'];
$new_posts = tz::shared()->news->getNewForWall($lastCustomerNewsID);
$output = '';
if ($new_posts) {
foreach ($new_posts as $new_post) {
$output .= "<div class='wall_post'>";
$output .= $new_post['message'];
$output .= "</div>";
}
} else {
}
echo $output;
}
Note - The function getNewForWall pulls records with an id greater than the argument passed in
This works fine when getting a new post, however the problem is that I need to update the "last id" to the "newest id" from the new records returned in ajax.php each time the function runs, because currently once its grabs the newest posts the first time, its keeps recognizing those as new on an ongoing basis.
How can I pass the newest "last id" from the array in ajax.php back to the AJAX function each time it runs? Can I pass a separate variable back to the AJAX function?
Thanks!
First of all, I think PHP here should return JSON instead of HTML information
JQuery should process JSON to generate HTML information
The PHP code looks like this (this is an example)
<?php
$page = $_POST['page'];
$method = $_GET['method'];
if ($method == "list") {
$limit = 20;
$offset = ($page - 1) * $limit;
$post = new Post();
// Calculate offsets according to page limits and page numbers and query articles
//Let's assume that the field of content is "content"
$offset = ($page - 1) * $limit;
$post_list = $post->offset($offset)->limit($limit)->select();
$total = $post->offset($offset)->limit($limit)->count(); //Statistics of all entries
//Get the largest ID by ID sort
$last_id = $post->order('id desc')->find();
$last_id = $last_id['id'];
echo json_encode([
'last_id' => $last_id,
'post_list' => $post_list,
"maxpage"=>ceil($total / $limit), //Calculate the maximum number of pages
]);
} elseif ($method == 'last_check') {
$post = new Post();
//Get the largest ID by ID sort
$last_id = $post->order('id desc')->find();
$last_id = $last_id['id'];
echo json_encode([
'last_id' => $last_id,
]);
}
Now we can check whether there are new articles through timers and page flips.
And you can use maxpage to determine if there is the next page.
function checkForNewPosts() {
$.ajax({
url: "example.com/ajax.php?method=last_check",
method: "get",
dataType:"json",
success:function(data)
{
if(data.last_id>lastCustomerNewsID){
//Write a new post operation here.
lastCustomerNewsID = data.last_id;
}
}
});
}
function getNextPage(){
var html;
page = page + 1;
$.ajax({
url: "example.com/ajax.php?method=list",
method: "post",
data:{
"page": page
},
dataType:"json",
success:function(data)
{
//Collate JSON into the required HTML format
html = "";
$.each(data.post_list, function(i, item){
html = html + "<div class='wall_post'>" + item.contect + "</div>";
});
if(data.last_id>lastCustomerNewsID){
//Write a new post operation here.
lastCustomerNewsID = data.last_id;
}
if(data.maxpage<=page){
//If there is no next page
}
$('#wall_posts').prepend(data);
}
});
}
setInterval(checkForNewPosts, 10000);
So I have the majority of my system working and I am stuck on one last bit
The GET is currentlyusing the same notification_id it gets from the while loop, so it constantly searches against that id for new records over and over.
LIKE SO...
jquery....4862996 (line 4)
GET http://viewajax.php?notification_id=43&_=1405814864693
jquery....4862996 (line 4)
GET http://viewajax.php?notification_id=43&_=1405814864694
What I'm looking to do is search the first notification_id from the while loop send it off to the server side viewajax.php to see if there is a new record and if there is insert it into its div, (which it currently does) but then use that same new notification_id from the server on its next ajax cycle for new records. I've tried everything and asked many questions and I've been looking high and low online for possible solutions to no avail.
Any help would be greatly appreciated and I will love you forever.
AJAX
<?
$user1_id=$_SESSION['id'];
$call="select * from notifications WHERE notification_targetuser='$user1_id' AND notification_status=1 ORDER BY notification_id DESC LIMIT 1";
$chant=mysqli_query($mysqli,$call) or die(mysqli_error($mysqli));
while($notification=mysqli_fetch_array($chant)){
?>
<script type="text/javascript">
function loadIt() {
var notification_id=<?php echo $notification['notification_id'] ;?>
$.ajax({
type: "GET",
url: "viewajax.php?notification_id="+notification_id,
dataType:"json",
cache: false,
success: function(data){
$("#notif_actual_text-"+notification_id).prepend('<div class="notif_ui"><div class="notif_text"><div id="notif_actual_text-'+data['notification_id']+'" class="notif_actual_text"><img border=\"1\" src=\"userimages/cropped'+data['notification_triggeredby']+'.jpg\" onerror=this.src=\"userimages/no_profile_img.jpeg\" width=\"40\" height=\"40\" ><br />'+data['notification_content']+' <br />'+data['notification_time']+'<br /></div></div></div></div>');
i = parseInt($("#mes").text()); $("#mes").text((i+data.num));
}
});
}
setInterval(loadIt, 10000);
</script>
<? }}?>
VIEWAJAX.php
if(isset($_GET['notification_id'])){
$id= mysqli_real_escape_string($mysqli,$_GET['notification_id']);
$user1_id= $_SESSION['id'];
$json = array();
$com=mysqli_query($mysqli,"select notification_id,notification_content,notification_time,notification_triggeredby from notifications where notification_id > '$id' AND notification_status='1' ");
echo mysqli_error($mysqli);
$num = mysqli_num_rows($com);
if($num>0){
$json['num'] = $num;
}else{
$json['num'] = 0;
}
$resultArr = mysqli_fetch_array($com);
$json['notification_id'] = $resultArr['notification_id'];
$json['notification_content'] = $resultArr['notification_content'];
$json['notification_triggeredby'] = $resultArr['notification_triggeredby'];
$json['notification_time'] = $resultArr['notification_time'];
mysqli_free_result($com);
echo json_encode($json);
}
EDIT
PHP SOURCE
{"num":0,"notification_id":null,"notification_content":null,"notification_triggeredby":null,"notification_time":null}
AJAX SOURCE
<script type="text/javascript">
function loadIt() {
var notification_id=44
$.ajax({
type: "GET",
url: "viewajax.php?notification_id="+notification_id,
dataType:"json",
cache: false,
success: function(data){
$("#notif_actual_text-"+notification_id).prepend('<div class="notif_ui"><div class="notif_text"><div id="notif_actual_text-'+data['notification_id']+'" class="notif_actual_text"><img border=\"1\" src=\"userimages/cropped'+data['notification_triggeredby']+'.jpg\" onerror=this.src=\"userimages/no_profile_img.jpeg\" width=\"40\" height=\"40\" ><br />'+data['notification_content']+' <br />'+data['notification_time']+'<br /></div></div></div></div>');
i = parseInt($("#mes").text()); $("#mes").text((i+data.num));
}
});
}
setInterval(loadIt, 10000);
</script>
Why don't you just update "notification_status" to 0 after you retrieve it in the php parts? Then it will not be retrieved again.
Why does this code work fine in the unit test, but not in the page? I have Firebug and FirePHP in place and can see the variable pass just fine if I hard code it, the operation is passing an int just fine in the unit test, but I've tried parseInt, Math.floor, and many other wacky methods and the value for statementCount simply won't post.
The ajax:
//polling code
var statementCount = 0;
(function poll(){
setTimeout(function(){
$.ajax({ url: "RROO_update.php",
type: "POST",
data: {'meetID': 2176, 'statementCount': statementCount},
success: function(data){
if(data.length > 0){
var statements = JSON.parse(data);
//reset the statement count
statementCount = statementCount + statements.length;
$(this).actplug_RROO('formatReturns', statements, userID);
poll();
}
},
error: function(){
poll();
},
});
}, 5000);
})();
and the php:
<?php
include("../inc/variables.php");
error_reporting (E_ALL ^ E_NOTICE);
require_once('../FirePHPCore/FirePHP.class.php');
require_once('../FirePHPCore/fb.php');
$firephp = FirePHP::getInstance(true);
ob_start();
$MeetingID = $_POST['meetID'];
$StatementCount = (int)$_POST['statementCount'];
$firephp-> log($StatementCount, 'Statement count passed in' );
$Finished = FALSE;
while($Finished == FALSE){
$MeetingStats = mysql_query("SELECT RROO_UPDATE.*, MEMBER.UserName, MEMBER.UserImage FROM RROO_UPDATE JOIN MEMBER ON RROO_UPDATE.MemberID = MEMBER.MemberID WHERE MeetingID = $MeetingID ORDER BY TimeStamp DESC", $DB_Connection);
$MyNum = mysql_num_rows($MeetingStats);
$firephp->log($MyNum, 'Row Query');
if($MyNum > $StatementCount){
$Returns = array();
while($Return = mysql_fetch_array($MeetingStats)){
array_push($Returns, $Return);
}
$NewReturns = array();
$NewStats = $MyNum - $StatementCount;
$firephp->log($NewStats, 'heres the new stats count');
for($i = 0; $i < $NewStats; $i++){
array_push($NewReturns, $Returns[$i]);
}
$Here = count($NewReturns);
$firephp->log($Here, 'The length of the new returns array');
$Finished = TRUE;
echo json_encode($NewReturns);
}
else{
sleep(3);
}
}
?>
Like I said, it comes back fine on the unit test which is the same in all the aspects I can see (I actually copy pasted it into the page) the only difference being that the postback is routed differently on the page (to the plugin) but I've messed around with callback to no avail. Is there some reason the statementCount won't reset and Post in this code?
I don't think that statementCount is defined inside the callback, only in the function which executes the ajax call.
Here is a question and answer which should help you do what you want.
How would I go about updating a div with a id every x seconds? I want it to update the users statuses which are contained inside this, that includes the time the amount of comments made on that individual post.
I've tried setInterval but it takes 10 seconds for the status to be added and then duplicates the status every x amounts of seconds after that. All I need is for the response data to be updated not the insertion of the comment to be re-added every 10 seconds.
HTML:
<div id='divider-"+response['streamitem_id']+'></div>
JavaScript:
$(document).ready(function(){
$("form#myform").submit(function(event) {
event.preventDefault();
var content = $("#toid").val();
var newmsg = $("#newmsg").val();
$.ajax({
type: "POST",
url: "insert.php",
cache: false,
dataType: "json",
data: { toid: content, newmsg: newmsg },
success: function(response){
$("#homestatusid").html("<div id='divider-"+response['streamitem_id']+"'><div class='userinfo'>X</div><a href='/profile.php?username="+response['username']+"'>"+response['first']+" "+ response['middle']+" "+response['last']+"<span class='subtleLink'> said</span><br/><a class='subtleLink' style='font-weight:normal;'>"+response['streamitem_timestamp']+"</a><hr>"+newmsg+"<div style='height:20px;' class='post_contextoptions'><div id='streamcomment'><a style='cursor:pointer;' id='commenttoggle_"+response['streamitem_id']+"' onclick=\"toggle_comments('comment_holder_"+response['streamitem_id']+"');clearTimeout(streamloop);swapcommentlabel(this.id);\">Write a comment...</a></div><div id='streamlike'><a id='likecontext_"+response['streamitem_id']+"' style='cursor:pointer;' onClick=\"likestatus("+response['streamitem_id']+",this.id);\"><div style='width:50px;' id='likesprint"+response['streamitem_id']+"'>Like</div></a><div style='width:50px;' id='likesprint"+response['streamitem_id']+"'></div></div><div id='streamdislike'><a id='dislikecontext_"+response['streamitem_id']+"' style='cursor:pointer;' onClick=\"dislikestatus("+response['streamitem_id']+",this.id);\"><div style='width:70px;' id='dislikesprint"+response['streamitem_id']+"'>Dislike</div></a><div style='width:70px;' id='dislikesprint"+response['streamitem_id']+"'></div></div></div><div class='stream_comment_holder' style='display:none;' id='comment_holder_"+response['streamitem_id']+"'><div id='comment_list_"+response['streamitem_id']+"'><table width=100%><tr><td valign=top width=30px><img class='stream_profileimage' style='border:none;padding:0px;display:inline;' border=\"0\" src=\"imgs/cropped"+response['id']+".jpg\" onerror='this.src=\"img/no_profile_img.jpeg\"' width=\"40\" height=\"40\" ></a><td valign=top align=left><div class='stream_comment_inputarea'><input id='addcomment' type='text' name='content' style='width:100%;' class='input_comment' placeholder='Write a comment...' onkeyup='growcommentinput(this);' autocomplete='off' onkeypress=\"if(event.keyCode==13){addcomment("+response['streamitem_id']+",this.value,'comment_list_"+response['streamitem_id']+"',"+response['id']+",'"+response['first']+" "+ response['middle']+" "+response['last']+"');this.value='';}\"><br/></div></div>");
}
});
return false
});
});
INSERT.PHP
$json = array();
$check = "SELECT streamitem_id FROM streamdata WHERE streamitem_creator='$user1_id' ORDER BY streamitem_id DESC";
$check1 = mysql_query($check);
$resultArr = mysql_fetch_array($check1);
$json['streamitem_id'] = $resultArr['streamitem_id'];
mysql_free_result($check1);
$check = "SELECT streamitem_timestamp FROM streamdata WHERE streamitem_creator='$user1_id' ORDER BY streamitem_timestamp DESC";
$check1 = mysql_query($check);
$resultArr = mysql_fetch_array($check1);
$json['streamitem_timestamp'] = Agotime($resultArr['streamitem_timestamp']);
mysql_free_result($check1);
$check = "SELECT username, id, first, middle, last FROM users";
$check1 = mysql_query($check);
$resultArr = mysql_fetch_array($check1);
$json['username'] = $resultArr['username'];
$json['id'] = $resultArr['id'];
$json['first'] = $resultArr['first'];
$json['middle'] = $resultArr['middle'];
$json['last'] = $resultArr['last'];
mysql_free_result($check1);
echo json_encode($json);
First wrap up the Ajax call in a single-execution function, with the callback function referring to the same:
$(function() {
(function ajaxcall() {
$.ajax({
url: 'foo.php',
data: {boo:'moo',goo:'loo'},
timeout: function() { ajaxcall(); },
success: function(data) {
//do somethng with the data
//done, now call the function again:
ajaxcall();
}
});
}());
});
Then in the PHP write something like:
$timeout = 30;
$pollinterval = .5;
$counter = 30;
while ($counter >= 0) {
//function which fetches fresh data and sets $test to true if data is returned
list($test,$dataarray) = fetchdata();
if ($test) { //JSON_encode the data array and send it
echo JSON_ENCODE($dataarray);
}
else { //no fresh data, query the db again after wating for some time)
usleep($pollinterval*1000);
$counter -= $pollinterval;
}
//timeout, return whetever you have!
echo JSON_ENCODE($dataarray);
You can use setInterval (see Documentation) or setTimeout (see Documentation).
Sounds like polling. You can include an AJAX call, that will send a request to a backend PHP script that will search the database for further update. if found, it will immediately return the new result. The client side JS on receiving the new data, will wait for say 30 seconds before making another request. If the PHP doesn't find any new data, then it will query the DB again, say after 5 seconds, and continue to do so until a script-defined timeout, say 25 seconds, occur. Then it will return an empty result, on receiving which the client side JS will immediately make another request.
I think this is what you're wanting, using Jquery:
HTML:
<div id="divider-whatever"></div>
Jquery:
$(document).ready(function() {
setInterval(function() {
div = $("#divider-whatever");
$.get(data.php, function(responseData) {
div.html(responseData);
}, 1000);
// change 1000 to whatever time you need
// change data.php to the file where your data is coming from
});
});
*not tested
Hope this helps!
I'm making a simple voter that takes either a "like" vote or "dislike" vote. Then, I count the total number of likes and dislikes and output the total numbers. I figured out how to put in the votes using Jquery Ajax, but the number of votes do not update after I put in a vote. I would like to update the $numlike and $numdislike variables using Jquery Ajax.
Here is the PHP script pertaining to the output:
$like = mysql_query("SELECT * FROM voter WHERE likes = 1 ");
$numlike = 0;
while($row = mysql_fetch_assoc($like)){
$numlike++;
}
$dislike = mysql_query("SELECT * FROM voter WHERE likes = 0 ");
$numdislike = 0;
while($row = mysql_fetch_assoc($dislike)){
$numdislike++;
}
echo "$numlike like";
echo "<br>";
echo "$numdislike dislike";
UPDATE:
Jquery Ajax for uploading vote
<script>
$(document).ready(function(){
$("#voter").submit(function() {
var like = $('#like').attr('value');
var dislike = $('#dislike').attr('value');
$.ajax({
type: "POST",
url: "vote.php",
data: "like=" + like +"& dislike="+ dislike,
success: submitFinished
});
function submitFinished( response ) {
response = $.trim( response );
if ( response == "success" ) {
jAlert("Thanks for voting!", "Thank you!");
}
return false;
});
});
</script>
<form id="voter" method="post">
<input type='image' name='like' id='like' value='like' src='like.png'/>
<input type='image' name='dislike' id='dislike' value='dislike' src='dislike.png'/>
</form>
vote.php:
if ($_POST['like'])
{
$likeqry = "INSERT INTO test VALUES('','1')";
mysql_query($likeqry) or die(mysql_error());
echo "success";
}
if ($_POST['dislike'])
{
$dislikeqry = "INSERT INTO test VALUES('','0')";
mysql_query($dislikeqry) or die(mysql_error());
echo "success";
}
If you want to change current like or dislike number after clicking it you must return result instead of printing it ! return json result and echo this and change div innerHTML to see new result !
............
............
............
$dislike = mysql_query("SELECT * FROM voter WHERE likes = 0 ");
$numdislike = 0;
while($row = mysql_fetch_assoc($dislike)){
$numdislike++;
}
echo json_encode( array( $numlike, $numdislike ) ) ;
exit();
Now in your html code :
$.ajax({
type: "POST",
url: "vote.php",
context:$(this)
data: "like=" + like +"& dislike="+ dislike,
success: submitFinished(data)
});
function submitFinished( response ) {
response = $.parseJSON( response );
//Now change number of like and dilike but i don't know where are shown in your html
$('#like').attr('value',response[0]);
$('#dislike').attr('value',response[1]);
return false;
});
You can send a $_GET or $_POST variable to the file that you are calling with AJAX.
.load("google.com", "foo=bar", function(){
});