thywill
Version:
A Node.js clustered framework for single page web applications based on asynchronous messaging.
126 lines (110 loc) • 3.98 kB
JavaScript
/**
* @fileOverview
* Draw class definition, a trivial example application.
*/
var util = require('util');
var path = require('path');
var fs = require('fs');
var async = require('async');
var Thywill = require('thywill');
var bootstrapManifest = require('./bootstrapManifest');
//-----------------------------------------------------------
// Class Definition
//-----------------------------------------------------------
/**
* @class
* A trivial example application.
*
* This application provides a UI for the client to draw on a canvas, and have
* the result show up on the canvas of every other connected client.
*/
function Draw (id) {
Draw.super_.call(this, id);
// The channel used to broadcast draw data.
this.channelId = 'draw';
}
util.inherits(Draw, Thywill.getBaseClass('Application'));
var p = Draw.prototype;
//-----------------------------------------------------------
// Initialization
//-----------------------------------------------------------
/**
* @see Application#_defineBootstrapResources
*/
p._defineBootstrapResources = function (callback) {
var self = this;
// Text encoding throughout.
var encoding = 'utf8';
// An array of functions load up bootstrap resources.
var fns = [
// Add resources from files listed in the bootstrap manifest.
function (asyncCallback) {
self.storeBootstrapResourcesFromManifest(bootstrapManifest, asyncCallback);
},
// Add the client Javascript separately, as it needs to be rendered as a
// template.
function (asyncCallback) {
// Load the file.
var originFilePath = path.resolve(__dirname, '../client/js/drawClient.js');
var data = fs.readFileSync(originFilePath, encoding);
// A little templating to insert the application ID.
data = self.thywill.templateEngine.render(data, {
applicationId: self.id,
uiTemplateId: 'draw-template-ui'
});
// Create and store the resource.
var resource = self.thywill.resourceManager.createResource(data, {
clientPath: '/draw/js/drawClient.js',
encoding: encoding,
originFilePath: originFilePath,
weight: 50
});
self.storeBootstrapResource(resource, asyncCallback);
}
];
async.series(fns, callback);
};
//-----------------------------------------------------------
// Methods
//-----------------------------------------------------------
/**
* @see Application#receivedFromClient
*/
p.receivedFromClient = function (client, message) {
// Data for a created path from paper.js.
var data = message.getData();
// Validate the data a little, just enough to make sure that the receiving
// clients won't error. Since this is an example only, no need to check
// everything.
if (!data || !Array.isArray(data.segments)) {
this.thywill.log.warn('Draw: invalid data received from client.' + message);
return;
}
// Create a broadcast message to send the data for this path to all connected
// clients except the one that sent this message.
this.sendToChannel(this.channelId, data, [client]);
};
/**
* @see Application#connection
*/
p.connection = function (client) {
var self = this;
this.thywill.log.debug('Draw: Client connected: ' + client.getConnectionId());
// Every client is subscribed to the same channel, used to broadcast updates.
this.subscribe(client, this.channelId, function (error) {
if (error) {
self.thywill.log.error(error);
}
});
};
/**
* @see Application#disconnection
*/
p.disconnection = function (client) {
// Do nothing except log it.
this.thywill.log.debug('Draw: Client disconnected: ' + client.getConnectionId());
};
//-----------------------------------------------------------
// Exports - Class Constructor
//-----------------------------------------------------------
module.exports = Draw;