I've been working on a project for a couple of Minecraft servers that use Bukkit. I'm trying to create a web page that contains a dynamic map of the servers' worlds, as well as a real-time event update system, where a <div> is updated as events happen on the server. To give a brief outline of how my system works, the Minecraft servers communicate events with a Node.js webserver over the same network via UDP packets, and the Node.js webserver uses these packets to build JavaScript objects containing the event info. The objects are then stored, and passed to Jade whenever the page is requested. Jade takes care of the templating.
What I want to do is update this page dynamically, so that the user doesn't have to refresh the entire page to update the list of events. What I'm trying to implement is something like the Facebook ticker, which updates every time a Facebook friend does something like posting a status, commenting on a post, or 'liking' a post.
In reading this question on SO, I've concluded that I need to use long polling in a PHP script, but I'm not sure of how to integrate PHP with a webserver written almost entirely in Node.js. How could I go about doing this?
EDIT:
I've run into a problem in the clientside code.
This is the script block:
script(src='/scripts/jadeTemplate.js')
script(src='/socket.io/socket.io.js')
script(type='text/javascript')
var socket = io.connect();
socket.on('obj', function(obj) {
var newsItem = document.createElement("item");
jade.render(newsItem, 'objTemplate', { object: obj });
$('#newsfeed').prepend(newsItem);
console.log(obj);
alert(obj);
});
And this is objTemplate.jade:
p #{object}
// That's it.
When the alert() and console.log() are placed at the top of the script, it alerts and logs, but at the bottom, they don't execute (hence, I think it's a problem with either the creation of newsItem, the jade.render(), or the prepend.
If I need to provide any more snippets or files let me know. I'm still tinkering, so I might solve it on my own, but unless I update, I still need help. :)
I'd skip PHP and take a look at socket.io. It uses websockets when possible, but it will fall back to long-polling when necessary, and the client side library is very easy to use.
Whenever your node.js server has a new object ready to go, it will push it to all connected browsers. Use ClientJade to render the object using your template (you may have to break out the relevant part of the main template into its own file), then prepend the generated dom element to your feed.
First, if it isn't this way already, you'll need to break out the relevant part of your jade template into its own file. Call it objTemplate.jade. Then use ClientJade to create a compiled template that can be run in the browser: clientjade objTemplate.jade > jadeTemplate.js. Put jadeTemplate.js in your public js directory.
In your node.js app, you'll have something like this (pseudo-codey):
var io = require('socket.io').listen(httpServer);
listenForUDPPackets(function(obj) {
saveObjSomewhere(obj);
io.sockets.emit('obj', obj);
});
Then on the client, something like this:
<script src="/js/jadeTemplate.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect();
socket.on('obj', function(obj) {
var newsItem = document.createElement();
jade.render(newsItem, 'objTemplate', obj);
$('#newsFeed').prepend(newsItem);
});
</script>
Related
Can someone please tell me if socket.io is only useful if the page your clients will use is a HTML page.
I want to create a node server that can push events to my existing PHP pages.
The pages are different and not suffixed with html.
All the examples I read use Chatroom examples with Index.html etc.
I simply want to know if what I want to do is even feasible.
Many thanks in advance.
When you write a php page the output is html. I hope that answers your question
PHP and socket.io work together. The only difference between doing it with html and with PHP is the way you link the two together (the common tutorial shows a way that only works with html, but there is another way that works with both html and php).
Try something like this (from a similar answer of mine, https://stackoverflow.com/a/25189436/3842050):
var socket = require('socket.io');
var express = require('express');
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = socket.listen(server);
Then remove the app.use and app.get as they are no longer needed for how this is going to be done. Then add server.listen(8000); at the end of the server.js. For dependencies, use: <script src="//cdn.socket.io/socket.io-1.0.0.js"></script>. Then, to run your server, go to it in terminal and type node server.js. Then just connect to it with your client. Also, for events, in the server, use:
io.on('connection', function (client) {
client.on('someEvent', function(someVariables){
//Do something with someVariables when the client emits 'someEvent'
io.emit('anEventToClients', someData);
});
client.on('anotherEvent', function(someMoreVariables){
//Do more things with someMoreVariables when the client emits 'anotherEvent'
io.emit('anotherEventToClients', someMoreData);
});
});
And in your client code:
socket.emit('someEvent', variables);
socket.on('anEventToClients', function(something){
//Code when anEventToClient is emitted from the server
});
I am aware that I can call PHP scripts after processing an AJAX request, but am I able to do it the other way around?
I am writing a dynamically sized navigation component for a new website and I want to refresh the nav every time a new item is added to the Menu.
In my menu class I am currently thinking of using this approach to achieve the effect:
public static function new_item($label, $link) {
$pos = self::num_items();
$DB = Database::getInstance();
$query = $DB->connection->prepare("INSERT INTO menu VALUES('', :label, :link, :pos )");
$query->execute(array(':label'=>$label,
':link' =>$link,
':pos' =>$pos+=1
));
?>
<script>
function refreshHeader() {
$.ajax({
type: "GET",
url: "my url",
success: function() {
// refresh the header here somehow
}
});
}
</script>
<?php
}
However, every time this runs I see nothing in my console (even when I put a valid url into my function), will I be able to achieve what I want this way or would I be better processing appending the tab to the document via AJAX and then calling the insert method in my Menu class on the success callback?
The only reason I ask is I feel this way may look neater in comparison to the other way of handling it, although I may be completely wrong.
Any feedback would be greatly appreciated - cheers
Alex.
echoing the following line can call out existing javascript functions and you are even able to insert variables (only strings and ints though).
echo "<style onload='jsfunction(\"$vars\")'></style>";
I find this one of the most simple ways to do this quickly.
Oh, I now understand what you want to do, what you need is websockets. When a piece of php code (sever side) is executed, you want something to happen in the browser (client side). Take a look at how live chats are made with javascript and websockets, long polling and other similar methods, that's what you need here.
This helped me a lot What are Long-Polling, Websockets, Server-Sent Events (SSE) and Comet?
I have been working with jquery/ajax requests. I have successfully got a ajax request which will retrieve data from a database, the problem is, that i'm constantly serving window.setInterval() to refresh this function every x amount of seconds.
How would I change this to keep the ajax request alive, so it updates the html content without having to serve multiple requests to my ajax script.
My code follows:
window.setInterval(function()
{
$(function ()
{
$.ajax({
url: 'Ajax.php'+SearchTerm, dataType: 'json', success: function(rows)
{
$('#NumberOfVotes').empty();
for (var i in rows)
{
var row = rows[i];
var QuestionID = row[0];
var Votes = row[1];
$('#NumberOfVotes')
.append(Votes);
}
}
});
});
}, 500);
A lot of this depends on how your server would be able to update it's content dynamically. That said, what you are looking for is websockets. Websockets are designed to replace the long-polling paradigm.
EDIT: Since you use mainly php for your server technology, look at Ratchet. I've heard good things about it http://socketo.me/
Here is an excellent article on using websockets with HTML
http://net.tutsplus.com/tutorials/javascript-ajax/start-using-html5-websockets-today/
.NET has a great socket library in SignalR
http://signalr.net/
There is a myriad of php documentation on sockets out there
http://php.net/manual/en/book.sockets.php
look into using web sockets - you could send the client a message anytime they need to go an look for new data - that way your not making any unnecessary requests. Try checking out pubnub -service is cheap and could handle everything you need.
You could set xhr.multipart = true and modify server code. see Multipart Responses Example Code. Alternative way is to use websockets as mentioned
You need something server side that keeps the request alive until it has something to return. This is usually called "Comet", "Long-polling" or "Push".
The principle is :
You send a request client-side via AJAX
Your server receives the request, and doesn't return a response yet. It sleeps/waits until it has something to return
A new entry in your database ! Your server now has something to return : it returns some JSON data for the waiting request
Your receive the response server side, display what you have to display, and go back to step 1 sending another request.
Now, the implementation server side will depend on the language/framework you are using.
Edit :
Some examples using PHP :
Comet and PHP
Simple Comet Implementation Using PHP and jQuery
I'm planning on converting a small PHP codebase (less than 1000 lines) to Node.js. It's a web app that contains about 50k lines of JS, so I figured I'd move it to Node.js. (Plus, PHP sucks donkey balls.) There's a few static files (CSS, HTML, etc.) that I'll be serving with the node-static package. My issue is with my PHP files that are not static.
For example, I have a search page that runs on a GET variable. I tack on ?keyword=blah onto the end of the URL and the PHP script searches the DB and outputs HTML for the browser. How do I replicate this behavior in Node.js? (In other words, how can I create a server to listen at localhost/search.html and accept GET variables in the URL?)
I know I can change the way searches are done to accomplish this, but I'd really like to figure out how to replicate this behavior since I have several scripts that act the same way.
EDIT: As for the database, I'm actually using OrientDB. But I don't connect directly to it, I use a set of Java services that I post JSON requests to. So really, all I need to be able to do is post a JSON request (synchronously) and output HTML.
Here's how I do it:
Create a new ExpressJS app
"express myapp"
Install all the dependencies
"cd myapp && npm install".
In app.js, make sure you require the "url" package before "var app"
var url = require('url');
Add a new route to "app.js" so that it looks for any GET requests to "search.html"
app.get('/search.html', function(req, res) {
// Process the request for the GET variables
var url_parts = url.parse(req.url, true);
var query = url_parts.query; // These are all your GET variables
var search_keyword = query.keyword;
if(search_keyword) {
// The keyword indeed exists
console.log(search_keyword);
}
res.end();
});
If you run the app and go to "search.html?keyword=haha", your console will output "haha". You can do anything after that with the keyword.
this is my first question in a forum ever i think ;-).
I will try to be as clear as possible with the question.
I´m trying to build a visual traceroute similar to that on yougetsignal.com by kirk ouimet.
It is actually working already using bash (traceroute,ping,host,) php/javascript, but I´m having some trouble with Javascript/AJAX.
Kirk updates the traced host-list periodically or via some kind of ajax-interrupt on the right side of the trace. I only know how to do it in one pass with one single Javascript xmlhttp-call and then echo a table into a standard w3school-livesearch-DIV.
http://www.yougetsignal.com/tools/visual-tracert/
I also don´t know if he does the traceroute with a cmd-line-tool like linux´s "traceroute".
Mine is working fine by first tracerouting, then doing reverse-lookup using "host" and then
pinging all hosts in the list again to get the rrt.
Is there any way to poll a txt-file (the traces) and then echo the output on demand to
a DIV?
I´m grateful for any hint.
Stefan
p.s.: the google-maps plotting works fine, it´s about the process of updating the traced-hosts
on demand for users (and me) to enjoy.
What you can do by using jQuery for ajax calls:
setInterval(function () {
$('#yourdiv').load('http://domain.com/yourfile');
}, 30000);
This code will load pregenerated html content to a specified div container every 30s. If you don't what to load a temporary generated html/php content, you can build an API and then add the data comming back dynamically on the DOM every time.
setInterval(function () {
$.getJSON('yourAPIUrl', function (data) {
$.each(data, function (item) {
// do something with the retrieved data, add it to the DOM for example
}
});
}, 30000);