@@ -0,0 +1,39 @@ | |||
# WebEvents | |||
This library provides an easy way to send events to a web browser (or any other | |||
client) over HTTP. | |||
## Usage | |||
See the `test.js` file for an example application. | |||
### Server | |||
``` | |||
var http = require("http"); | |||
var WebEvents = require("webevnts"); | |||
var events = WebEvents(); | |||
http.createServer(function(req, res) { | |||
/* | |||
* Whatever else your app does on each request | |||
*/ | |||
events.handle(req, res); | |||
}); | |||
// Emit whatever events you need | |||
events.emit("someevent", { some: "parameters" }); | |||
``` | |||
### Client | |||
``` | |||
var events = WebEvents(); | |||
// Listen to events | |||
events.on("someevent", function(evt) { | |||
// evt -> { some: "parameters" } | |||
}); | |||
``` |
@@ -0,0 +1,84 @@ | |||
(function() { | |||
function post(url, cb) { | |||
var xhr = new XMLHttpRequest(); | |||
xhr.addEventListener("load", function() { | |||
var obj = JSON.parse(xhr.responseText); | |||
if (obj.error) { | |||
cb(obj.error); | |||
} else { | |||
cb(null, obj); | |||
} | |||
}); | |||
xhr.addEventListener("error", function(err) { | |||
cb(err); | |||
}); | |||
xhr.open("POST", url); | |||
xhr.send(); | |||
} | |||
window.WebEvents = function() { | |||
var self = {}; | |||
var cbs = {}; | |||
var key = null; | |||
function emit(name, args) { | |||
if (!cbs[name]) | |||
return; | |||
cbs[name].forEach(function(cb) { | |||
cb(args); | |||
}); | |||
} | |||
function init(time) { | |||
post("/webevents/register", function(err, res) { | |||
// Retry on error | |||
if (err) { | |||
console.error(err); | |||
time = time || 1000; | |||
setTimeout(function() { init(time * 2) }, time); | |||
return; | |||
} | |||
key = res.key; | |||
await(); | |||
}); | |||
} | |||
function await(time) { | |||
post("/webevents/await/"+key, function(err, res) { | |||
// Retry registering on error | |||
if (err) { | |||
console.error(err); | |||
time = time || 1000; | |||
setTimeout(function() { init(time * 2) }, time); | |||
return; | |||
} | |||
res.forEach(function(evt) { | |||
emit(evt.name, evt.args); | |||
}); | |||
await(); | |||
}); | |||
} | |||
self.on = function(name, cb) { | |||
if (!cbs[name]) | |||
cbs[name] = []; | |||
cbs[name].push(cb); | |||
}; | |||
init(); | |||
return self; | |||
} | |||
})(); |
@@ -0,0 +1,77 @@ | |||
var crypto = require("crypto"); | |||
function Listener() { | |||
var self = {} | |||
var key = crypto.randomBytes(16).toString("hex"); | |||
self.key = key; | |||
var events = []; | |||
var waiter = null; | |||
function respond() { | |||
waiter.end(JSON.stringify(events)); | |||
waiter = null; | |||
events = []; | |||
} | |||
self.emit = function(name, args) { | |||
events.push({ name: name, args: args }); | |||
if (waiter != null) { | |||
respond(); | |||
} | |||
} | |||
self.handle = function(res) { | |||
waiter = res; | |||
if (events.length > 0) { | |||
respond(); | |||
} | |||
} | |||
return self; | |||
} | |||
function WebEvents() { | |||
var self = {} | |||
var listeners = {}; | |||
self.emit = function(name, args) { | |||
for (var i in listeners) { | |||
listeners[i].emit(name, args); | |||
} | |||
} | |||
self.handle = function(req, res) { | |||
var parts = req.url.substring(1).split("/"); | |||
if (parts[0] !== "webevents") | |||
return; | |||
res.writeHead(200, { "content-type": "application/json" }); | |||
if (parts[1] === "register") { | |||
var listener = Listener(); | |||
listeners[listener.key] = listener; | |||
res.end(JSON.stringify({ key: listener.key })); | |||
} else if (parts[1] === "await") { | |||
var listener = listeners[parts[2]]; | |||
if (!listener) { | |||
res.end(JSON.stringify({ | |||
error: "Listener "+parts[2]+" not registered" | |||
})); | |||
return; | |||
} | |||
listener.handle(res); | |||
} | |||
} | |||
return self | |||
} | |||
module.exports = WebEvents; |
@@ -0,0 +1,11 @@ | |||
{ | |||
"name": "webevents", | |||
"version": "1.0.0", | |||
"description": "A simple library for sending events from the server to the client.", | |||
"main": "index.js", | |||
"scripts": { | |||
"test": "echo \"Error: no test specified\" && exit 1" | |||
}, | |||
"author": "Martin Dørum Nygaard <martid0311@gmail.com> (https://www.mort.coffee)", | |||
"license": "ISC" | |||
} |
@@ -0,0 +1,60 @@ | |||
var http = require("http"); | |||
var Eventer = require("."); | |||
var fs = require("fs"); | |||
var html = | |||
"<!DOCTYPE html>"+ | |||
"<html>"+ | |||
"<head>"+ | |||
"<title>WebEvents</title>"+ | |||
"</head>"+ | |||
"<body>"+ | |||
"<div "+ | |||
"id='thing' "+ | |||
"style='position: absolute; width: 30px; height: 30px; background: blue;'></div>"+ | |||
"<script src='/client.js'></script>"+ | |||
"<script>"+ | |||
"var events = WebEvents();"+ | |||
"events.on('move', function(evt) {"+ | |||
"var elem = document.getElementById('thing');"+ | |||
"elem.style.top = evt.y+'px';"+ | |||
"elem.style.left = evt.x+'px';"+ | |||
"});"+ | |||
"</script>"+ | |||
"</body>"+ | |||
"</html>"; | |||
var eventer = Eventer(); | |||
http.createServer(function(req, res) { | |||
if (req.url == "/") { | |||
res.end(html); | |||
} else if (req.url == "/client.js") { | |||
fs.createReadStream("client.js") | |||
.pipe(res) | |||
.on("error", err => res.end(err.toString())); | |||
} else if (req.url.indexOf("/webevents") === 0) { | |||
eventer.handle(req, res); | |||
} | |||
}).listen(8080); | |||
// Just keep track of some coordinates to send to the client as events | |||
var x = 0; | |||
var y = 0; | |||
var vx = 30; | |||
var vy = 30; | |||
setInterval(() => { | |||
if (x < 0) | |||
vx = Math.abs(vx); | |||
else if (x > 1000) | |||
vx = -Math.abs(vx); | |||
if (y < 0) | |||
vy = Math.abs(vy); | |||
else if (y > 600) | |||
vy = -Math.abs(vy); | |||
x += vx; | |||
y += vy; | |||
eventer.emit("move", { x: x, y: y }); | |||
}, 100); |