I want to constantly read a JSON-formatted js file so my page shows the changes of that file.
I want some content in my page to change everytime I change the database file within the directory.
My files are:
objectoJSON.js:
var rightFencer;
rightFencer = {"name":"Jorge ANZOLA","nacionality":"VEN","points":10};
var leftFencer;
leftFencer = {"name":"John DOE","nacionality":"USA","points":5};
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<center><p id="rightFencerName"></p><p id="rightFencerPoints"></p> - <p id="leftFencerName"></p> <p id="leftFencerPoints"></p></center>
<script src="objetoJSON.js"></script>
<script>
document.getElementById("rightFencerName").innerHTML = rightFencer.name;
document.getElementById("leftFencerName").innerHTML = leftFencer.name;
document.getElementById("rightFencerPoints").innerHTML = rightFencer.points;
document.getElementById("leftFencerPoints").innerHTML = leftFencer.points;
</script>
</body>
</html>
I thought about putting those two scripts into an infinite while loop so by the time I change the file in the directory, it'd change. But it didn't work.
Also, I thought about using setInterval() to run the scripts every few seconds, but I didn't know how to make it work.
As you can see, I'm a complete noob, so ANY idea would be very appreciated.
Your "objectoJSON.js" is not a JSON file... it's a simple javascript object.
A JSON file would be something like this.
{
"rightFencer":{
"name":"Jorge ANZOLA",
"nacionality":"VEN",
"points":10
},
"leftFencer":{
"name":"John DOE",
"nacionality":"USA",
"points":5
}
}
What you are searching for is
Ajax, Server Sent Events or webSockets
Those update the pagecontent without the need to refresh the page or clicking something.
The following codes shows how to interact with each technology.
They have many advantages and disadvantages... to many to write right now.
ask specific and i can add that to the answer.
All the following examples are pure javascript and so don't need any type of library.They work with almost all new browsers... ios,android,windows also.
All the following examples could be adapted to work with a non properly formatted json file like that you posted. Look at the bottom.
Ajax:
Client asks for data
This updates the client every 30seconds.
function $(a){
return document.getElementById(a)
}
function ajax(a,b,c){ // Url, Callback, just a placeholder
c=new XMLHttpRequest;
c.open('GET',a);
c.onload=b;
c.send()
}
function reloadData(){
ajax('database.js',updateText)
};
function updateText(){
var db=JSON.parse(this.response);
$("rightFencerName").innerHTML=db.rightFencer.name;
$("leftFencerName").innerHTML=db.leftFencer.name;
$("rightFencerPoints").innerHTML=db.rightFencer.points;
$("leftFencerPoints").innerHTML=db.leftFencer.points;
}
window.setInterval(reloadData,30000);//30 seconds
/*setinterval is a very bad way to update stuff ,
especially with ajax.. there are many other ways to do that.*/
Ajax does not need any type of server if you read the JS file locally.
Also appendding it... but both examples are time based... and that is not good if you have many users online. WS & SSE allow you to update each user individually depending on the necessity.
SSE:
Server sends data when needed
This uses php to create a Server Sent Events Server
Also this updates the client every 30 seconds, but in this case the server updates the client. Using Ajax the client asks the server to update.
The php file "sse.php"
header('Content-Type: text/event-stream'); // specific sse mimetype
header('Cache-Control: no-cache'); // no cache
while(true) {
if(/*something changes*/){
echo "id: ".time().PHP_EOL;
echo "data: ".$data.PHP_EOL;
echo PHP_EOL;
}
ob_flush(); // clear memory
flush(); // clear memory
sleep(30);// seconds
}
The javascript file
function $(a){
return document.getElementById(a)
}
function updateText(e){
var db=JSON.parse(e.data);
$("rightFencerName").innerHTML=db.rightFencer.name;
$("leftFencerName").innerHTML=db.leftFencer.name;
$("rightFencerPoints").innerHTML=db.rightFencer.points;
$("leftFencerPoints").innerHTML=db.leftFencer.points;
}
var sse=new EventSource("sse.php");
sse.onmessage=updateText;
WebSockets:
Server sends data when needed, Client asks for data when needed
webSockets is cool ... comunication is bidirectional. it is fast. but you need something like a nodejs server to be able to handle it properly.
function $(a){
return document.getElementById(a)
}
function updateText(e){
var db=JSON.parse(e.data);
$("rightFencerName").innerHTML=db.rightFencer.name;
$("leftFencerName").innerHTML=db.leftFencer.name;
$("rightFencerPoints").innerHTML=db.rightFencer.points;
$("leftFencerPoints").innerHTML=db.leftFencer.points;
}
var ws=new WebSocket('ws://YOURIP:YOURPORT');
/*ws.onopen=function(){ //those events are also aviable with sse
ws.send('WS open!');//sending data to the server
};
ws.onclose=function(){
console.log('WS closed!');
};*/
ws.onmessage=updateText;
Adapting the js
Ajax..
load the "objectoJSON.js" with ajax and evulate it ... but not using eval(). eval is evil. use new Function()
function updateText(){
document.getElementById("rightFencerName").innerHTML = rightFencer.name;
document.getElementById("leftFencerName").innerHTML = leftFencer.name;
document.getElementById("rightFencerPoints").innerHTML = rightFencer.points;
document.getElementById("leftFencerPoints").innerHTML = leftFencer.points;
}
(new Function(this.response+'\n updateText()'))();
or append the script every 30 seconds or whatever....
I don't write that example as it is the worst approach.
With 30 clients it means that you have to read the file from server evey second.
With SSE or WS you read it once and broadcast it to hundreds of clients.
I suggest to fix your json file.
if you have any other questions ask.
I guess you are working with framework which supports websockets.
You could listen for a change in file using websocket.it may return change in data set like new record or update on any record, or using javascript/ajax call get latest content from server and update your HTML.
https://www.websocket.org/demos.html, see foreign exchange dashboard to see how websockets can be used for constantly updating data.
The way you are doing it now isn't scalable, testable or manageable.
You really don't want to save data on the server using plaintext json files.
If you want a more robust framework for handling your use case, I suggest using web sockets on both the client side and server side (socket.io is a great choice), and using RethinkDB on your server as the DB.
Related
I am trying to work out how EventSource might help solve an update problem with a web applications.
I would like to be able to notify visitors to a web page when one or another visitor has performed an update. The idea is:
One visitor makes some changes to a text area and submits.
The data is submitted using Ajax.
At the server, the changes are saved.
I would like the server to send a notification that changes have been made
I would like all other visitors to get this notification.
On the server in PHP, I have something like this:
if(isset($_POST['save'])) {
// process changes
$data = sprintf('data: {"time": "%s","type": "save"}',$date);
header("Cache-Control: no-store");
header("Content-Type: text/event-stream");
print "event: ping\n$data\n\n";
ob_flush();
flush();
exit;
}
In JavaScript I have something like this:
var eventSource = new EventSource("https://example.net/ajax.php", { withCredentials: true } );
eventSource.addEventListener("ping", (event) => {
const time = JSON.parse(event.data).time;
const type = JSON.parse(event.data).type;
console.log(`Ping at ${time} for ${type}`);
});
That doesn’t do the job at all. At the client end I get get an error message about the wrong headers (I think that it’s because there’s no save yet, so the PHP falls through to an empty string).
All the samples I have seen include a while(true) loop in the PHP, but non have a one-off event.
Is this possible to implement, and, if so, how?
Is it possible to set PHP session variables using Javascript?
In JavaScript:
jQuery('#div_session_write').load('session_write.php?session_name=new_value');
In session_write.php file:
<?
session_start();
if (isset($_GET['session_name'])) {$_SESSION['session_name'] = $_GET['session_name'];}
?>
In HTML:
<div id='div_session_write'> </div>
The session is stored server-side so you cannot add values to it from JavaScript. All that you get client-side is the session cookie which contains an id. One possibility would be to send an AJAX request to a server-side script which would set the session variable. Example with jQuery's .post() method:
$.post('/setsessionvariable.php', { name: 'value' });
You should, of course, be cautious about exposing such script.
If you want to allow client-side manipulation of persistent data, then it's best to just use cookies. That's what cookies were designed for.
or by pure js, see also on StackOverflow :
JavaScript post request like a form submit
BUT WHY try to set $_session with js? any JS variable can be modified by a player with
some 3rd party tools (firebug), thus any player can mod the $_session[]! And PHP cant give js any secret codes (or even [rolling] encrypted) to return, it is all visible. Jquery or AJAX can't help, it's all js in the end.
This happens in online game design a lot. (Maybe a bit of Game Theory? forgive me, I have a masters and love to put theory to use :) ) Like in crimegameonline.com, I
initialize a minigame puzzle with PHP, saving the initial board in $_SESSION['foo'].
Then, I use php to [make html that] shows the initial puzzle start. Then, js takes over, watching buttons and modding element xy's as players make moves. I DONT want to play client-server (like WOW) and ask the server 'hey, my player want's to move to xy, what should I do?'. It's a lot of bandwidth, I don't want the server that involved.
And I can just send POSTs each time the player makes an error (or dies). The player can block outgoing POSTs (and alter local JS vars to make it forget the out count) or simply modify outgoing POST data. YES, people will do this, especially if real money is involved.
If the game is small, you could send post updates EACH move (button click), 1-way, with post vars of the last TWO moves. Then, the server sanity checks last and cats new in a $_SESSION['allMoves']. If the game is massive, you could just send a 'halfway' update of all preceeding moves, and see if it matches in the final update's list.
Then, after a js thinks we have a win, add or mod a button to change pages:
document.getElementById('but1').onclick=Function("leave()");
...
function leave() {
var line='crimegameonline-p9b.php';
top.location.href=line;
}
Then the new page's PHP looks at $_SESSION['init'] and plays thru each of the
$_SESSION['allMoves'] to see if it is really a winner. The server (PHP) must decide if it is really a winner, not the client (js).
You can't directly manipulate a session value from Javascript - they only exist on the server.
You could let your Javascript get and set values in the session by using AJAX calls though.
See also
Javascript and session variables
jQuery click event to change php session variable
One simple way to set session variable is by sending request to another PHP file. Here no need to use Jquery or any other library.
Consider I have index.php file where I am creating SESSION variable (say $_SESSION['v']=0) if SESSION is not created otherwise I will load other file.
Code is like this:
session_start();
if(!isset($_SESSION['v']))
{
$_SESSION['v']=0;
}
else
{
header("Location:connect.php");
}
Now in count.html I want to set this session variable to 1.
Content in count.html
function doneHandler(result) {
window.location="setSession.php";
}
In count.html javascript part, send a request to another PHP file (say setSession.php) where i can have access to session variable.
So in setSession.php will write
session_start();
$_SESSION['v']=1;
header('Location:index.php');
Not possible. Because JavaScript is client-side and session is server-side. To do anything related to a PHP session, you have to go to the server.
be careful when doing this, as it is a security risk. attackers could just repeatedly inject data into session variables, which is data stored on the server. this opens you to someone overloading your server with junk session data.
here's an example of code that you wouldn't want to do..
<input type="hidden" value="..." name="putIntoSession">
..
<?php
$_SESSION["somekey"] = $_POST["putIntoSession"]
?>
Now an attacker can just change the value of putIntoSession and submit the form a billion times. Boom!
If you take the approach of creating an AJAX service to do this, you'll want to make sure you enforce security to make sure repeated requests can't be made, that you're truncating the received value, and doing some basic data validation.
I solved this question using Ajax. What I do is make an ajax call to a PHP page where the value that passes will be saved in session.
The example that I am going to show you, what I do is that when you change the value of the number of items to show in a datatable, that value is saved in session.
$('#table-campus').on( 'length.dt', function ( e, settings, len ) {
$.ajax ({
data: {"numElems": len},
url: '../../Utiles/GuardarNumElems.php',
type: 'post'
});
});
And the GuardarNumElems.php is as following:
<?php
session_start();
if(isset ($_POST['numElems'] )){
$numElems = $_POST['numElems'];
$_SESSION['elems_table'] = $numElems;
}else{
$_SESSION['elems_table'] = 25;
}
?>
I've been searching and experimenting and I just can't seem to figure this out. I would appreciate any insight. Thank you!
So I have a Shopify store and I have an Webhook that triggers when I make a sale, meaning it pushes JSON data of that sale to a PHP script on my server. Right now I'm having that PHP script insert the relevant data into a database and mark that sale as "unread." Then, I would have a separate HTML/JavaScript page that I would run separately, polling the server to check for unread sales ever 10 seconds or so. There's a little more to that, but that's the general idea. It's clunky and I would like to modernize this.
Here's what I've been trying and can't seem to get working.
Set up an EventSource page that's listening to a separate PHP script.
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sales Notification!</title>
</head>
<body>
<div id="widget">
<div id="notification_box"></div>
</div>
<script type="text/javascript">
if (!!window.EventSource) {
var source = new EventSource('alert_listener.php');
} else {
console.log("Window.EventSource fail!");
}
source.addEventListener('message', function(e) {
console.log(e.data);
}, false);
source.addEventListener('open', function(e) {
// Connection was opened.
}, false);
source.addEventListener('error', function(e) {
if (e.readyState == EventSource.CLOSED) {
// Connection was closed.
}
}, false);
</script>
</body>
</html>
That actually works well when I do something simple like this example. Anyway, here's my PHP code listening for the JSON sent from the Websocket (some of this code is provided by Shopify):
<?php
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
error_reporting(0);
define('SHOPIFY_APP_SECRET', 'NOT_PUBLIC_HAR_HAR');
function verify_webhook($data, $hmac_header) {
$calculated_hmac = base64_encode(hash_hmac('sha256', $data, SHOPIFY_APP_SECRET, true));
return ($hmac_header == $calculated_hmac);
}
function sendMsg($id, $msg) {
echo "id: $id" . PHP_EOL;
echo "data: $msg" . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
$hmac_header = $_SERVER['HTTP_X_SHOPIFY_HMAC_SHA256'];
$data = file_get_contents('php://input');
$verified = verify_webhook($data, $hmac_header);
while (1) {
if ($data !== "") {
sendMsg("test id", "Data: " . $data);
}
sleep(1);
}
?>
When I push data from Shopify to this PHP script, the first JavaScript example is supposed to be listening for this data, but nothing happens. Not a thing. I have no idea why. I have no idea how to tell the PHP script to say, "Hey! An order came in! Yo JavaScript, do something!" and then the JavaScript go, "New order received! Let's do a thing!"
TLDR:
Shopify pushes JSON to a PHP script (via a webhook)
Separate JavaScript file listens to this PHP script via EventSource object and reacts accordingly
I can't get this to work. Please help.
That is all. Thank you.
I saw this on Twitter - and no, this can be answered.
First of I have to admit that I am not familiar all too well with EventSource - but from what I see, you are using exactly one script to do two things at once; obtaining the Shopify data and immediately exporting it to JS. However, each PHP script ran has exactly one request and response context - and in this case, you have been echo'ing your data all the way back to Shopify.
You will need two endpoints:
The first endpoint acts as the receipient to Shopify's webhooks (shopify_webhook.php). Each time it receives data, you might store it in a database for fire-and-forget actions like Redis, where you set a possibly low TTL. As far as I know, Redis also has queues - so this would probably be a better approach.
The second endpoint is your event source that keeps streaming incoming queue entries to your requesting JavaScript (i.e. shopify_eventsource.php).
Redis here is just a suggestion - but one way or another, you will have to use an intermediate storage to be able to move the incoming data to another output channel. You can write all this in one PHP file where you validate the incoming request to see if it is a Shopify request (and stream) or if it is your JavaScript code requesting the output. But using two endpoints and thus separating code might make it more readable and adjustable should Shopify change APIs or you your own JavaScript receipient.
TL;DR:
Shopify -> Your endpoint -> intermediate storage.
Intermediate storage -> your endpoint -(stream)> your javascript.
So I made a website that displays FPS information stored in a mysql database. For each second of gameplay I have a pair of number(fps)-image(screenshot).
I display the numbers in a line chart made with JavaScript. The behaviour desired is when I click on a bullet in the chart, the screenshot for that particular second is displayed in a div on the page.
I have to mention that the screenshots are stored in the database and they are very low in size. I display then using PHP like this:
$query = "SELECT `image` FROM `logs` WHERE `session_id`=".$_GET['session']." AND `second`=".$second;
$sth = $mysqli->query($query);
$result=mysqli_fetch_array($sth);
if (!empty($result))
echo ' <img id="screen" src="data:image/jpg;base64,'.base64_encode($result['image']).'"/>';
The method I'm using now is when I click on a bullet in the chart (action recorded in JS), I send it as a GET parameter and read it with PHP afterwards, like this:
window.location.href = url + "?second=" + second;
This method obviously will refresh my page. The problem is, the chart I made also has a zoom/scroll option and that resets whenever the page is refreshed, making the experience very bad for the user.
Is there any method to display the screenshots without refreshing the page, for this particular case (where I have to query the database for each click/picture)? Maybe there is a better way of approaching this problem?
Thanks.
I think you've got 2 solutions which are Ajax or Websocket depending your needs.
AJAX
Ajax permit to asynchronously, only when you need, call the server and get datas from an URL which could be a webservice or PHP page... Perhaps, it's the better solution in your case.
To make it easy, you can use JQuery library by donwloading the script and insert it in your HTML :
<script src="jquery-3.0.0.min.js"></script>
To call the server, using JQuery :
$.ajax({
url: url + "/yourphppage.php",
data: "parameter=" + yourOptionelParameter,
async: false,
success: function(data) {
refreshYourChart(data);
},
error: function() {
alert("Your error");
},
contentType: 'charset=utf-8'
});
Or if your prefer pure javascript.
Now, you just have to work on the presentation of your data, on the server side. It could be what you want HTML, TXT, JSON, XML...
Websocket
Websocket is like a permanent tunnel opened between your server and the client. Each side can ask or send datas in real time.
It seems to be a library server side :
http://socketo.me/
And client side, it's very easy :
Nice documentation on mozilla website
Hope it helps. Good luck.
To change a picture source, as I see the easiest way is using an ajax call, so you can send any kind of parameters to your server, and in return your will get your new picture source.
$.get('urlToYourServer.com?parameter=1', function(data){
$('#img').attr('src', data.imgSrc);
})
What I am trying to do:
I have a ready made HTML5 game incorporated onto my website - Link to game
Using this game, I want to now implement a high score board and display it on the same page.
Example, if I am logged in as Conor, Conor goes to snake_game.php where the game is located. He gets a score of three, I need the value of three, which currently is assigned to a JavaScript variable, to become a PHP variable so that I can store it into a table called high_scores in my database.
Then, once the data is in my database, I can start showing the results on the high score variable and update the data when needed.
Problem(s):
I understand that I have to use AJAX to achieve this, but I have never used AJAX before.
Resources:
snake_game.php is where the container is located where the game is displayed, as well as the high scores div:
<div id="wrapper">
<div class="game_canvas">
<canvas id="canvas" width="450" height="450"></canvas>
<script src="javascript/snake.js"></script>
</div>
<div class="high_scores" >
High scores:
</div>
</div>
snake.js is where all the JavaScript is found to create the game. All the JavaScript is available to view in the link above.
What I have tried:
From the game's JS, I believe the score is kept in a var called score - var score; - Knowing this, I have tried the below approach in an attempt to get . I have tried to watch a few tutorials online and have come up with this (located in snake_game.php):
<script type="text/javascript">
function updateScore ()
{
var score = $('score').val();
$.post('snake_game.php', {postscore: score},
function ()
{
$('high_scores').html(data);
});
}
</script>
and then PHP code:
<?php
$new_highscore= $_POST['score'];
echo json_encode($new_highscore);
?>
I believe the following get's data from the JS? But I am not sure, nor do I think it is the correct way to approach this.
Any/all help would be appreciated :)
If I were you I would not do this in vanilla php but of course you can.
Things to note:
1) You're not passing your response data into your call back method in your jQuery post
2) you aren't selecting anything with jquery
$.post('snake_game.php', {postscore: score},
function (data) // <-- pass data in here;
{
$('high_scores').html(data); //<!-- you aren't selecting anything here.
//if I were you I would make data a json
//I would have something like
$('.high_scores').append(data.high_score);
//actually I have no idea why you even have this callback here
});
3) I don't really understand you're explanation of snake_game.php. It seems like you are trying to use it as both a template and an endpoint. If you are doing things in vanilla php, which I strongly discourage you from doing, you need another php file to handle your post request. e.g. snake_high_scores.php.
//in snake_high_scores.php
//this is a really bad way to learn ajax requests. You should use a framework
$new_highscore= $_POST['score'];
//store this score in a db maybe you can pickup the user id from a session cookie
echo json_encode({data => {high_score => $some_highscore}});
In addition to above answers I would suggest whenever game loads make the high score available in page (place in a hidden element/input field if you don't want to show to user) then once the game ends then compare the user score with high score if it is greater than current one then make the Ajax call to php to store in DB.
This works for both per user (make user high score available once user logs in) or global single high score.
You can't access 'score' outside the "ready" function. If you want to implement things the way you were thinking above, you'll have to add a global reference to score, though I'll warn you that's generally frowned upon.
// Make a global reference to score
var score;
$(document).ready(function(){
//Canvas stuff
var canvas = $("#canvas")[0];
var ctx = canvas.getContext("2d");
var w = $("#canvas").width();
var h = $("#canvas").height();
//Lets save the cell width in a variable for easy control
var cw = 10;
var d;
var food;
//var score; THIS NOT NEEDED ANYMORE.
You're better off adding your function with the Ajax call within the ready() function just like the code from the tutorial. The way the game works is everytime you run into a wall, the game resets itself by calling the "init" function. To do what you're wanting, before the score gets reset to zero, you want to send it to the server. See below for an idea:
function init()
{
d = "right"; //default direction
create_snake();
create_food(); //Now we can see the food particle
// Before resetting the score below, send the user score
// to the server
sendScoreToServer(score);
//finally lets display the score
score = 0;
........
EDIT:
Freddy, here's the simplest Ajax demo I can give you. You need to study this and fiddle with it until you understand what's going on. After you understand this demo below, you should be able to figure out how to do what you want above. YOU WILL NEED TO EDIT THE <SCRIPT> FILE PATHS AND AJAX URL TO AJAXDEMO.PHP IN MY EXAMPLE FILES TO MATCH YOUR SYSTEM.
In some HTML file:
<!DOCTYPE html>
<html>
<head>
<title>Ajax Demo</title>
</head>
<body>
<input type="text" name="score" id="scoreBox"><button id="sendScore">Send Score to Server Running PHP</button>
<div id="result">The result from the server will be placed here...</div>
<script src="/resources/js/jquery-1.12.3.js"></script>
<script src="/resources/js/ajaxDemo.js"></script>
</body>
</html>
ajaxDemo.js file:
// This function uses AJAX to send the score from the HTML page running javascript to a web server running PHP.
function sendScoreToServer(theScore) {
$.ajax({
type: "POST",
url: "http://localhost/ajaxDemo.php",
data: { score: theScore },
dataType: 'json',
success: function(response){
console.log(response);
$('#result').html('The score returned by the server is: '+response.scoreDoubled);
}
});
}
// Once the HTML page finishes loading, this binds a 'onClick' event to the button that causes it to trigger the sendScoreToServer function.
$( document ).ready(function() {
$('#sendScore').on('click', function() {
var score = $('#scoreBox').val();
sendScoreToServer(score);
});
});
In ajaxDemo.php file on the server:
<?php
$result = [];
$result['scoreDoubled'] = $_POST['score'] * 2;
echo json_encode($result);
Final Encouragement:
It sounds to me like you might be slightly confused regarding front-end code vs. back-end code and what the difference is. Just remember that Front-End code runs on the USER'S computer. So when you visit that game tutorial website and it loads the Snake game... that game is running on YOUR computer. Back-End code (PHP is a back-end language) is code that runs on a web server... meaning generally NOT on your computer. By running a web server on your machine with "localhost", you are essentially having your PC 'pretend' to be a web site so you can quickly test and develop your application. Thus any Ajax calls to 'localhost' never have to leave your machine. HOWEVER, in a normal usage environment, an Ajax call would be sending a request over the internet to some remote server such as www.MySite.com. MySite.com would then process the info sent to it using PHP or some other language, then send a response back, which gets processed by the "success" function attached to the ajax request. The "success" function (commonly called a 'callback' function) then updates the HTML page with some result based on what the server sent back.