I'm playing a bit around with push notifications, and want to update a page whenever there's a change in the database.
I have this from http://www.screenr.com/SNH:
<?php
$filename = dirname(__FILE__).'/data.php';
$lastmodif = isset($_GET['timestamp']) ? $_GET['timestamp'] : 0;
$currentmodif = filemtime($filename);
while ($currentmodif <= $lastmodif) {
usleep(10000);
clearstatcache();
$currentmodif = filemtime($filename);
}
$response = array();
$response['msg'] = file_get_contents($filename);
$response['timestamp'] = $currentmodif;
echo json_encode($response);
?>
My data.php is a script getting data from a JSON file:
<script>function itnews_overview() {
$.getJSON('/ajax.php?type=itnews_overview', function(data) {
$.each(data.data, function(option, type) {
$('.bjqs').append('<li><span class="date">'+ type.submitted +'<br />'+ type.time +'</span><h2>' + type.title + '</h2><p>' + type.content + '</p></li>');
});
});
}
</script>
<script>
itnews_overview();
</script>
<div id="news">
<ul class="bjqs"></ul>
</div>
UPDATE: Code from index.php:
<script type="text/javascript">
var timestamp = null;
function waitForMsg() {
$.ajax({
type: "GET",
url: "getData.php?timestamp=" + timestamp,
async: true,
cache: false,
success: function(data) {
var json = eval('(' + data + ')');
if(json['msg'] != "") {
$(".news").html(json['msg']);
}
timestamp = json['timestamp'];
setTimeout('waitForMsg()',1000);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
setTimeout('waitForMsg()',15000);
}
});
}
$(document).ready(function(){
waitForMsg();
});
</script>
As this file isn't saved when I add something to the database, filemtime won't work — is there another way I can check if new rows has been added to the table?
UPDATE: Trying to solve this with SSE.
I have two files, index.php and send_sse.php (inspiration from http://www.developerdrive.com/2012/03/pushing-updates-to-the-web-page-with-html5-server-sent-events/)
index.php:
<div id="serverData">Content</div>
<script type="text/javascript">
//check for browser support
if(typeof(EventSource)!=="undefined") {
//create an object, passing it the name and location of the server side script
var eSource = new EventSource("send_sse.php");
//detect message receipt
eSource.onmessage = function(event) {
//write the received data to the page
document.getElementById("serverData").innerHTML = event.data;
};
}
else {
document.getElementById("serverData").innerHTML="Whoops! Your browser doesn't receive server-sent events.";
}
</script>
send_sse.php:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$url = "content.json";
$str = file_get_contents($url);
$data = json_decode($str, TRUE);
//generate random number for demonstration
//echo the new number
echo "data: " . json_encode($data);
ob_flush();
?>
This, however, doesn't seem to work, which is probably because SSE needs plain text data. I just can't figure out how to do that and then wrap that content in a couple of HTML tags.
UPDATE: Okay, so now it's sort of working with SSE, thanks to VDP. I have the following:
$sql= "SELECT title, content, submitted FROM `flex_itnews` where valid = 1 order by submitted desc";
$query= mysql_query($sql);
setlocale(LC_ALL, 'da_DK');
while($result = mysql_fetch_array($query)){
echo "data: <li><span class='date'>". strftime('%e. %B', strtotime($result['submitted'])) ."<br />kl. ". strftime('%H.%M', strtotime($result['submitted'])) ."</span><h2>" . $result['title']. "</h2><p>" . $result['content'] ."</p></li>\n";
}
However, when I add anything new, it just echoes data: data: data. If I refresh the page, it displays correctly.
UPDATE: Using livequery plugin:
<script>
var source = new EventSource('data2.php');
source.onmessage = function (event) {
$('.bjqs').html(event.data);
};
$('#news').livequery(function(){
$(this).bjqs({
'animation' : 'slide',
'showMarkers' : false,
'showControls' : false,
'rotationSpeed': 100,
'width' : 1800,
'height' : 160
});
});
</script>
UPDATE: Trying to use delegate()
<script>
$("body").delegate(".news", "click", function(){
$("#news").bjqs({
'animation' : 'slide',
'showMarkers' : false,
'showControls' : false,
'rotationSpeed': 100,
'width' : 1800,
'height' : 160
});
var source = new EventSource('data2.php');
source.onmessage = function (event) {
$('.bjqs').append(event.data);
};
});
</script>
Yes! There are multiple (better) ways:
websocket (the best solution but not supported on older or mobile browsers)
Server sent events (SSE) (sort of polling but optimized just for the task you ask for)
Long polling (like you are doing)
Flash sockets
other plugin based socket stuff
ajax polling
I've posted another answer with examples about it before
I listed several transport methods. websockets being the ideal (because it's the only 2 way communication between server and client), SSE being my second choice. You won't need the $.getJSON method. The overall idea will be the same.
On the server side (php in your case) you query your database for changes. You return the data as JSON (json_encode(data) can do that). On the client side you decode the JSON (JSON.parse(data) can do that). With the data you received you update your page.
Just the polling like you where doing causes more overhead because you are doing lots of request to the server.
SSE is more "I want to subscribe to a stream" and "I want to stop listening". => less overhead
Websockets is more: "I set up a connection. I talk server listens. Server talks client listens" A full duplex connection. => least overhead
SSE Code example
The page the client goes to (for example index.html or index.php)
It's just a normal html page containing this javascript:
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script>
//javascript:
var source = new EventSource('data.php');
source.onmessage = function (event) {
//here you do the stuff with the received messages.
//like log it to the console
console.log(event.data);
//or append it to div
$('#response').append(event.data);
};
</script>
</head>
<body>
<div id="response"></div>
</body>
</html>
The 'data.php' page:
<?php
/* set the header first, don't echo/print anything before this header is set! Else the default headers will be set first then this line tries to set the headers and results in an error because the header is already set. */
header("Content-Type: text/event-stream\n\n");
//query the database
$sql= "SELECT COUNT(*) FROM `messages`";
$query= mysql_query($sql);
$result = mysql_fetch_array($query);
$count = $result[0];
//return the data
echo "data: " . $count. "\n";
?>
So you only need those 2 pages.
UPDATE:
I had only seen your comments not the updates.. sorry ;)
if you use .delegate() you shouldn't use body but try a selector as high up the tree as possible (.bjqs in your case).
In you're case you don't even need live,delegate,on or all that! Just apply the bjqs again afther the content is updated.
var source = new EventSource('data2.php');
source.onmessage = function (event) {
$('.bjqs').html(event.data);
$("#news").bjqs({
'animation' : 'slide',
'showMarkers' : false,
'showControls' : false,
'rotationSpeed': 100,
'width' : 1800,
'height' : 160
});
};
This will give you issues too because you are constantly re-initializing bjqs and it isn't written to handle dynamically updating content. What you can do is send only data (with php) if there is new data. Check if the call returns empty, if not update:
var source = new EventSource('data2.php');
source.onmessage = function (event) {
if(event.data !=""){
$('.bjqs').html(event.data);
$("#news").bjqs({
'animation' : 'slide',
'showMarkers' : false,
'showControls' : false,
'rotationSpeed': 100,
'width' : 1800,
'height' : 160
});
}
};
You can count number of rows in a table, and than check if the number of rows is changed.
Without digging into your code too much im answering the question in the title:
add last modified column to your table, this has a built in mysql trigger that updates whenever the row is added or changes:
ALTER TABLE `yourTable`
ADD COLUMN `last_modified` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
ADD INDEX (`last_modified`);
and then query it like,
SELECT * FROM yourTable where last_modified > ?
("?" is the pdo placeholder you replace with last queried timestamp)
Related
I need some example to display POST data inside HTML DIV element. Like this: Beeceptor
I make an example using PHP and jQuery.
It works fine but I don't know if there a better solution instead of using SESSIONS and interval function?
The POST data is made by using an external program (not by jQuery itself).
PHP
session_id('13245');
session_start();
$session_id = session_id();
if($data['payload'] !== null)
{
$_SESSION['payload'] = $data['payload'];
$_SESSION['timestamp'] = microtime();
}
else
{
$_SESSION['payload'] = $_SESSION['payload'];
$_SESSION['timestamp'] = $_SESSION['timestamp'];
}
echo json_encode(array('timestamp' => $_SESSION['timestamp'], 'payload' => $_SESSION['payload']));
?>
jQuery
$(document).ready(function () {
var oldTimeStamp = 0;
setInterval(function()
{
$.ajax({
type:"post",
url:"post.php",
datatype:"json",
success:function(data)
{
var obj = jQuery.parseJSON(data)
if(oldTimeStamp != obj.timestamp)
{
oldTimeStamp = obj.timestamp;
$('#displayData').append('timestamp: ' + obj.timestamp);
$('#displayData').append(' rawPayload: ' + obj.payload);
$('#displayData').append('<br />');
}
}
});
}, 1000);//time in milliseconds
});
Any help will be greatly appreciated.
you can go for "then()" or "done()", immediate after finishing ajax call. here is the sample:
$.ajax({
type:"post",
url:"post.php",
datatype:"json",
success:function(data)
{...}
}).then(function (data){
var obj = jQuery.parseJSON(data)
if(oldTimeStamp != obj.timestamp)
{
oldTimeStamp = obj.timestamp;
$('#displayData').append('timestamp: ' + obj.timestamp);
$('#displayData').append(' rawPayload: ' + obj.payload);
$('#displayData').append('<br />');
}
});
You are trying to make a real-time application such as chatting and real-time visualizations. In order to achive this I suggest you to write with NodeJs SOCKET.IO
If you use PHP it will make your server lode more harder than JavaScript programs like socket.io.
Your Question:
It works fine but I don't know if there a better solution instead of using SESSIONS and interval function?
Answer:
Definitely it's a bad practice which trigger the server every seconds even there are no new updates. Let's assume you have 100 users online at the same time so your server will be called 100 times every second which is really a more load to the server.
Example:
https://socket.io/get-started/chat
Guys m working on my first live project and i am stuck at a point, where i need help with ajax jquery. i can do this with PHP but i wanna do this with ajax.
Here if user enter a product code ,so i want to compare this product code value into my database and show product name in my other form ,which will open after user input value:
Here in first field i want product name:
Here in my table you can see product code and product name:
ok so here is my html code in last option when user enter product code
Here is jquery i am sending user data to 8transectiondata.php to compare
And this is php file and i want $data['product_name']; to show
Here's a generic answer.
JS FILE:
$(document).ready(function () {
$('#myButtonId').on('click', function () {
var code = $('#myCodeInputId').val();
if (code !== '') { // checking if input is not empty
$.ajax({
url: './my/php/file.php', // php file that communicate with your DB
method: 'GET', // it could be 'POST' too
data: {code: code},
// code that will be used to find your product name
// you can call it in your php file by "$_GET['code']" if you specified GET method
dataType: 'json' // it could be 'text' too in this case
})
.done(function (response) { // on success
$('#myProductNameInput').val(response.product_name);
})
.fail(function (response) { // on error
// Handle error
});
}
});
});
PHP FILE:
// I assumed you use pdo method to communicate with your DB
try {
$dbh = new PDO('mysql:dbname=myDbName;host=myHost;charset=utf8', 'myLogin', 'myPassword');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch(PDOException $e) {
exit('ERROR: ' . $e->getMessage());
}
$sql = "SELECT `product_name` FROM `products` WHERE `product_code` = :code";
$result = $dbh->prepare($sql);
$result->bindValue('code', $_GET['code'], PDO::PARAM_INT);
$result->execute();
if($result->rowCount()) { // if you got a row from your DB
$row = $result->fetchObject();
echo json_encode($row, JSON_UNESCAPED_UNICODE); // as we use json method in ajax you've got to output your data this way
// if we use text method in ajax, we simply echo $row
}
else {
// handle no result case
}
I know what you want to do, but without specific code the best I can do is give you a generalized answer.
When a user fills out a field, you want to post that field to the server, look up a product and return some stuff.
The basics are going to look like this.
$(document).ready( function(){
//rolling timeout
var timeout;
$('#field').on('keyup', function(e){
if(timeout) clearTimeout(timeout);
timeout = setTimeout( function(){
var data = {
"field" : $('#field').val()
};
$.post( '{url}', data, function(response){
if(response.debug) console.log(response.debug);
if(response.success){
//open other form
$('{otherFormProductField}').val(response.product);
}
}); //end post
},450); //end timeout
});//end onKeyup
}); //end onReady
Then in PHP, you have to process the request. Pull the field from the $_POST array, look it up in the Database. Then build a response array and send it back to the client as JSON. I like to build responses in a structure something like this.
{
success : "message", //or error : "message"
debug : "",
item : ""
}
Then in PHP I will do this.
ob_start();
..code..
$response['debug'] = ob_get_clean();
header("Content-type:application/json");
echo json_encode($response);
This way, you can still print out debug info (in side the output buffer calls ) when developing it and don't have to worry about it messing up the Json or the header call.
-note- Use a timeout, that you reset on each key press (a rolling timeout). What it does is reset the previous timeout each time the key is released. That way it only sends the request once the user quits typing (instead of sending request on every keypress). I have found 450 milliseconds to be about the perfect value for this. Not too long not too short. Basically once they stop typing for 450ms it will trigger the $.post
I want to create notification system in my company's erp similar to Facebook one. To maintain good performance, I use long polling - looped ajax querying php script for number of seconds.
Everything works fine, until I try to go to another page inside ERP. When I click any link on the page, everything freezes waiting until background php script is completed, even if I manually killed ajax connection.
JS script is included on every page and starts itself on page load.
function notificationsObject(){
var nl = new Object();
nl.startAjax = function(data){
if(nl.ajaxObject != null) try{ nl.ajaxObject.abort() } catch(e){} finally{nl.ajaxObject = null}
nl.ajaxObject = $.ajax({
url: nl.ajaxUrl, //declared before function declaration
type: 'POST',
data: {data: data}
}).done(function(responseText){nl.ajaxSuccess(responseText)
}).fail(function(responseText){nl.ajaxFail(responseText)});
}
nl.ajaxSuccess = function(response){
console.debug(response);
nl.startAjax();
}
nl.ajaxFail = function(response){
//#todo some code here
}
nl.killConnection = function(){
if(nl.ajaxObject != null) try{ nl.ajaxObject.abort() } catch(e){} finally{nl.ajaxObject = null}
console.debug('killing');
}
(more code here)
return nl;
}
init code looks like this
$(document).ready(function(){
var notifications = notificationsObject();
notifications.startAjax({name: 'startup'});
setTimeout(function(){window.onbeforeunload = function(){notifications.killConnection()};}, 1000);
});
and there's also some PHP code:
public function executeUsersNotificationListener(){
ignore_user_abort(false);
ob_end_flush();
$this->getResponse()->setHttpHeader("Cache-Control", "no-cache");
$this->getResponse()->setHttpHeader("Pragma", "no-cache");
$this->getResponse()->setHttpHeader("Expires", 0);
$timeLimit = 30;
set_time_limit($timeLimit+1);
echo 'test';
$i = 0;
while($i++ < $timeLimit){
echo " ";
sleep(1);
}
return sfView::NONE;
}
as you can see above, I did some research and used ignore_user_abort and so on, but it won't work.
I am making a notification system similar to the red notification on facebook. It should update the number of messages sent to a user in real time. When the message MYSQL table is updated, it should instantly notify the user, but it does not. There does not seem to be an error inserting into MYSQL because on page refresh the notifications update just fine.
I am essentially using code from this video tutorial: http://www.screenr.com/SNH (which updates in realtime if a data.txt file is changed, but it is not written for MYSQL like I am trying to do)
Is there something wrong with the below code:
**Javascript**
<script type="text/javascript">
$(document).ready(function(){
var timestamp = null;
function waitForMsg(){
$.ajax({
type: "GET",
url: "getData.php",
data: "userid=" + userid,
async: true,
cache: false,
success: function(data){
var json = eval('(' + data + ')');
if (json['msg'] != "") {
$('.notification').fadeIn().html(json['msg']);
}
setTimeout('waitForMsg()',30000);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
setTimeout('waitForMsg()',30000);
}
});
}
waitForMsg();
</script>
<body>
<div class="notification"></div>
**PHP***
<?php
if ($_SERVER['REQUEST_METHOD'] == 'GET' )
{
$userid = $_GET['userid'];
include("config.php");
$sql="SELECT MAX(time) FROM notification WHERE userid='$userid'";
$result = mysql_query($sql);
$row = mysql_fetch_assoc($result);
$currentmodif = $row['MAX(time)'];
$s="SELECT MAX(lasttimeread) FROM notificationsRead WHERE submittedby='$userid'";
$r = mysql_query($s);
$rows = mysql_fetch_assoc($r);
$lasttimeread = $rows['MAX(lasttimeread)'];
while ($currentmodif <= $lasttimeread) {
usleep(10000);
clearstatcache();
$currentmodif = $row['MAX(time)'];
}
$response = array();
$response['msg'] = You have new messages;
echo json_encode($response);
}
?>
there is a problem with your javascript line below
url: "getData.php",
data: "userid" + userid,
async: true,
remove the = sign and try again.
i have not read the whole code but found this is the cause test and feel free to reply if still got more issues.
You're not re-executing the SQL statement in the loop so the value in "$row['MAX(time)']" is never going to change.
If you re-execute the query in the loop this example may work--but executing a query every 10ms is not going to be a very efficient way to implement real-time notification.
Also, if the PHP script runs longer then the time configured in php.ini (max_execution_time, 30 secs by default), you'll get an error.
I am new to WebOS Dev and just started before a week. So, need a little bit help.
From last 2 days I'm stuck in one problem.
I want to display my server side data to client mobile, with the help of palm sample project I am able to display static posted data on client mobile(display every time same posted data values).
But, I want to post value from text box(Display data which is posted via textbox).
if you already installed webos SDK then you can find the sourcecode from here
C:\Program Files\Palm\SDK\share\samplecode\samples\Data\....
just try to run both method AJAX GET and AJAX POST , i want to do some thing like in AJAX GET method(Google ex.)
my modified code is
ajaxPost-assistant.js (i want to add textbox in this code and display data which is posted by this page )
var myassistant = null;
function AjaxPostAssistant()
{
}
AjaxPostAssistant.prototype.setup=function()
{
myassistant = this;
this.textFieldAtt = {
hintText: 'hint',
textFieldName: 'name',
modelProperty: 'original',
multiline: false,
disabledProperty: 'disabled',
focus: true,
modifierState: Mojo.Widget.capsLock,
limitResize: false,
holdToEnable: false,
focusMode: Mojo.Widget.focusSelectMode,
changeOnKeyPress: true,
textReplacement: false,
maxLength: 30,
requiresEnterKey: false
};
this.model = {
'original' : 'Palm',
disabled: false
};
this.controller.setupWidget('sendField', this.textFieldAtt, this.model);
this.buttonModel1 = {
buttonLabel : 'Push to send post',
buttonClass : '',
disable : false
}
this.buttonAtt1 = {
//type : 'Activity'
}
this.controller.setupWidget('post_button',this.buttonAtt1,this.buttonModel1)
Mojo.Event.listen(this.controller.get('post_button'),Mojo.Event.tap,this.handlePost.bind(this));
}
AjaxPostAssistant.prototype.handlePost=function(event)
{
var posturl='http://openxcellca.info/Parthvi/webos/ajaxpost1.php';
var postdata='fname=Ajay';
var myAjax = new Ajax.Request(posturl, {
method: 'post',
evalJSON: 'force',
postBody: postdata,
contentType: 'application/x-www-form-urlencoded',
onComplete: function(transport){
if (transport.status == 200)
myassistant.controller.get('area-to-update').update('Success!');
else {
myassistant.controller.get('area-to-update').update('Failure!');
}
myassistant.controller.get('server-response').update('Server Response: \n' + transport.responseText);
},
onFailure: function(transport){
myassistant.controller.get('area-to-update').update('Failure!\n\n' + transport.responseText);
}
});
}
AjaxPostAssistant.prototype.activate = function(event) {
/* put in event handlers here that should only be in effect when this scene is active. For
example, key handlers that are observing the document */
}
AjaxPostAssistant.prototype.deactivate = function(event) {
/* remove any event handlers you added in activate and do any other cleanup that should happen before
this scene is popped or another scene is pushed on top */
}
AjaxPostAssistant.prototype.cleanup = function(event) {
/* this function should do any cleanup needed before the scene is destroyed as
a result of being popped off the scene stack */
}
ajaxPost-scene.htm
<div x-mojo-element="Button" id="post_button"></div>
<div id="area-to-update"></div>
<br>
<div id="server-response"></div>
ajaxpost1.php
<?php
$con = mysql_connect("localhost","user","pwd");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("db", $con);
$qry = "SELECT * FROM user WHERE fname='.$_POST['fname'].'";
$result = mysql_query($qry);
while($row = mysql_fetch_array($result))
{
echo "Name:-".$row['fname'];
echo "<br />";
echo "E-mail:-".$row['email'];
echo "<br />";
echo "Phone:-".$row['phone'];
echo "<br />";
}
mysql_close($con);
?>
Please help me, I want to make one sync app for my college project.
And I need to complete in this 3 weeks.
I'm no WebOS expert, but first make sure that your php server side script is sending JSON. It's much clearer to handle the response: see my question here
Then it should be pretty easy.