I need help to launch my project on my website.
My question is: Might there be technical limitations of my webhost to launch my project online?
I'm rather new to programming and started by doing the agar.io project from The Coding Train .
My project is running on localhost, there are obviously some things I can and I wish to improve in the future. But for now I'm wondering if it is possible to launch my project into my website to play with my project online and showcase it at job markets.
I read that a socket.io project is only for localhost-projects, but I'm somehow skeptical if that is true.
As mentioned I'm rather new and don't know where to start looking.
I would appreciate a hint where the problem might be.
I tried to change the socket and server to my website obviously but I have the feeling that I'm just poking in the dark to solve my problem.
The git repo is Agario
and the server.js:
// Based off of Shawn Van Every's Live Web
// http://itp.nyu.edu/~sve204/liveweb_fall2013/week3.html
var blobs = \[\];
function Blob(id, x, y, r) {
this.id = id;
this.x = x;
this.y = y;
this.r = r;
}
// Using express: http://expressjs.com/
var express = require('express');
// Create the app
var app = express();
// Set up the server
// process.env.PORT is related to deploying on heroku
var server = app.listen(process.env.PORT || 3000, listen);
// This call back just tells us that the server has started
function listen() {
var host = server.address().address;
var port = server.address().port;
// var port = process.env.PORT;
console.log('Example app listening at http://' + host + ':' + port);
}
app.use(express.static('public'));
// WebSocket Portion
// WebSockets work with the HTTP server
var io = require('socket.io')(server);
setInterval(heartbeat, 240);
function heartbeat() {
io.sockets.emit('heartbeat', blobs);
}
// Register a callback function to run when we have an individual connection
// This is run for each individual user that connects
io.sockets.on(
'connection',
// We are given a websocket object in our function
function(socket) {
console.log('We have a new client: ' + socket.id);
socket.on('start', function(data) {
console.log(socket.id + ' ' + data.x + ' ' + data.y + ' ' + data.r);
var blob = new Blob(socket.id, data.x, data.y, data.r);
blobs.push(blob);
});
socket.on('update', function(data) {
//console.log(socket.id + " " + data.x + " " + data.y + " " + data.r);
var blobi = new Blob(0, 0, 0);
for (var i = 0; i < blobs.length; i++) {
if (socket.id == blobs[i].id) {
blobi = blobs[i];
blobi.x = data.x;
blobi.y = data.y;
blobi.r = data.r;
}
}
// blob.x = data.x;
// blob.y = data.y;
// blob.r = data.r;
});
socket.on('disconnect', function() {
console.log('Client has disconnected');
});
}
);
// io.sockets.on('connection',
// // We are given a websocket object in our function
// function (socket) {
//
// console.log("We have a new client: " + socket.id);
//
// // When this user emits, client side: socket.emit('otherevent',some data);
// socket.on('start',
// function(data) {
// console.log(socket.id + " " + data.x + " " + data.y + " " + data.r);
// var blob = new Blob(socket.id, data.x, data.y, data.r);
// blobs.push(blob);
// }
// );
//
//
// socket.on('update',
// function(data) {
// // console.log(socket.id + " " + data.x + " " + data.y + " " + data.r);
// // var blob = new Blob(socket.id, data.x, data.y, data.r);
// // blobs.push(blob);
// var blob;
// for(var i=0; i\<blobs.length; i++) {
// if(socket.id == blobs\[i\].id) {
// blob = blobs\[i\];
// }
// }
// blob.x = data.x;
// blob.y = data.y;
// blob.r = data.r;
// }
// );
//
// socket.on('disconnect', function() {
// console.log("Client has disconnected");
// });
// }
// );
// var express = require('express');
// var app = express();
// var server = app.listen(3000);
// app.use(express.static('public'));
// console.log("My socket server is running");
// var socket = require('socket.io');
// var io = socket(server);
// io.sockets.on('connection', newConnection);
//
// function newConnection(socket) {
// console.log('new connection: ' + socket.id);
// socket.on('mouse', mouseMsg);
// function mouseMsg(data) {
// socket.broadcast.emit('mouse', data);
// console.log(data)
// }
// }
And my sketch.js is:
var socket;
var blob;
var id;
var blobs = \[\];
var zoom = 1;
function setup() {
createCanvas(600, 600);
// Start a socket connection to the server
// Some day we would run this server somewhere else
socket = io.connect('http://localhost:3000');
blob = new Blob(random(width), random(height), random(8, 24));
// Make a little object with x and y
var data = {
x: blob.pos.x,
y: blob.pos.y,
r: blob.r
};
socket.emit('start', data);
socket.on('heartbeat', function(data) {
//console.log(data);
blobs = data;
});
}
function draw() {
background(0);
// console.log(blob.pos.x, blob.pos.y);
translate(width / 2, height / 2);
var newzoom = 64 / blob.r;
zoom = lerp(zoom, newzoom, 0.1);
scale(zoom);
translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length - 1; i >= 0; i--) {
var id = blobs[i].id;
if (id.substring(2, id.length) !== socket.id) {
fill(0, 0, 255);
ellipse(blobs[i].x, blobs[i].y, blobs[i].r * 2, blobs[i].r * 2);
fill(255);
textAlign(CENTER);
textSize(4);
text(blobs[i].id, blobs[i].x, blobs[i].y + blobs[i].r);
}
// blobs[i].show();
// if (blob.eats(blobs[i])) {
// blobs.splice(i, 1);
// }
}
blob.show();
if (mouseIsPressed) {
blob.update();
}
blob.constrain();
var data = {
x: blob.pos.x,
y: blob.pos.y,
r: blob.r
};
socket.emit('update', data);
}
// blobs\[i\].show();
// if (blob.eats(blobs\[i\])) {
// blobs.splice(i, 1);
// }
// var blob;
// var blobs = \[\];
// var zoom = 1;
// function setup() {
//
// createCanvas(600, 600);
// socket = io.connect('http://localhost:3000/');
// blob = new Blob(random(width), random(height), random(8, 24));
//
// var data = {
// x: blob.pos.x,
// y: blob.pos.y,
// r: blob.r
// };
//
// socket.emit('start', data);
//
// socket.on('heartbeat',
// function(data) {
// // console.log(data);
// blobs = data;
// }
//
// );
// }
//
// function draw() {
// background(0);
//
// // translate(width/2-blob.pos.x, height/2-blob.pos.y);
// translate(width/2, height/2);
// var newzoom = 64 / blob.r;
// zoom = lerp(zoom, newzoom, 0.1);
//
// scale(zoom);
// translate(-blob.pos.x, - blob.pos.y)
// // console.log("-----------");
// for (var i=blobs.length-1; i\>=0; i--) {
// var id = blobs\[i\].id;
// // console.log("-----------");
// // console.log(id.substring(2, id.length));
// // console.log("-----------");
// if (id.substring(2, i.length) !== socket.id) {
// fill(0, 0, 255);
// ellipse(blobs\[i\].x, blobs\[i\].y, blobs\[i\].r \* 2, blobs\[i\].r \* 2);
//
//
// fill(255);
// textAlign(CENTER);
// textSize(4);
// // text(blobs\[i\].id, blobs\[i\].x, blobs\[i\].y + blobs\[i\].r);
// }
// // var id = blobs\[i\].id;
// // if (id.substring(2, id.length) !== socket.id) {
// // fill(0, 0, 255);
// // ellipse(blobs\[i\].x, blobs\[i\].y, blobs\[i\].r \* 2, blobs\[i\].r \* 2);
// //
// // fill(255);
// // textAlign(CENTER);
// // textSize(4);
// // text(blobs\[i\].id, blobs\[i\].x, blobs\[i\].y + blobs\[i\].r);
// // }
// // blobi = blobs\[i\];
// // blobi.show();
// // if(blob.eats(blobi)) {
// // blobs.splice(i, 1);
// // }
//
// }
//
// blob.show();
// if (mouseIsPressed) {
// blob.update();
// }
// blob.constrain();
//
// var data = {
// x: blob.pos.x,
// y: blob.pos.y,
// r: blob.r
// };
// socket.emit('update', data);
// }
Related
What is working
I created a node https/websocket server using WebSocket-Node. Here a snippet on how I add key/cert :
import WebSockerServer from "websocket";
import fs from "fs";
const httpsSignalServer = https.createServer(
{
key: fs.readFileSync("./server.private.key"),
cert: fs.readFileSync("./server.crt"),
},
(req, res) => {
console.log("signal server : we have received a request");
}
);
const signalWebsocket = new WebSockerServer.server({
httpServer: httpsSignalServer,
});
signalWebsocket.on("request", (request) => onRequest(request));
httpsSignalServer.listen(8080, () => console.log("My signal server is listening"));
I have a React html web page that sends data to server above with WebSocket web api via wss :
new WebSocket("wss://192.168.230.138:8081");
My react app runs in an https server. So far everything works.
What is not working
The problem is my little node websocket client. I am still using WebSocket-Node. The client documentation shows a tlsOptions to be given to the constructor.
Client code snippet:
var WebSocketClient = require("websocket").client;
var fs = require("fs");
const tlsOptions = {
key: "./server.private.key",
cert: "./server.crt",
};
var client = new WebSocketClient({
key: fs.readFileSync(tlsOptions.key),
cert: fs.readFileSync(tlsOptions.cert),
});
.
.
.
client.connect("wss://localhost:8080/", "");
The client returns the message :
Error: unable to verify the first certificate
Is there anyone out there who knows how to do the client setup with the tlsOptions?
Thank you
I wrote a perfectly functional simple chat script which is using secured connection. I added a couple of simple chat commands to enable or disable the chat from entering commands in chat.You could use this if you like or parts of it or even just see how I did it. Hope you find some use for it.
var maxLength = 100; // chars per chat
const port = 1441;
var JoinLeaveMsg = 1
var fs = require('fs');
const HTTPS = require('https');
const WebSocket = require('ws');
const server = new HTTPS.createServer({
cert: fs.readFileSync('C:/Certbot/live/MyDomain.com/cert.pem'),
key: fs.readFileSync('C:/Certbot/live/MyDomain.com/privkey.pem')
});
const wss = new WebSocket.Server({ server })
wss.on('connection', function connection(ws) {
const now = new Date();
const tDate = now.toDateString();
const date = new Date(now);
const currentDate = date.toLocaleTimeString();
console.log(tDate + ' - ' + currentDate + " - New User Connected");
ws.send(JSON.stringify(
{
name: "welcome",
message: "wanna chat?"
}
));
ws.on('message', function(message){
message = JSON.parse(message);
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');
const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);
// START CONNECT
if(message.type == "name"){
// START CHECKS FOR DOUBLE LOGIN
var dirty = message.data;
const ConnectingUser = DOMPurify.sanitize(dirty);
if (ConnectingUser != ''){
wss.clients.forEach(function e(client) {
var ConnectedUser = client.personName;
if(ConnectedUser == ConnectingUser) {
client.send(JSON.stringify(
{
name: "***Server***",
message: "***We do not allow double logins!"
}
));
client.send(JSON.stringify(
{
name: "***Server***",
message: "🔴 Disconnected..."
}
));
client.close();
}
});
}
// END CHECKS FOR DOUBLE LOGIN
ws.personName = ConnectingUser;
memberJoinedChatMsg(ws, ConnectingUser);
return;
}
// START INPUT DATA
if(message.type == "message"){
var ConnectedUser = ws.personName;
if (ConnectedUser != ''){
var dirty = message.message;
const Message = DOMPurify.sanitize(dirty);
var string = Message;
var temp = string.split(" ");
var CommandOne = temp[0];
var CommandTwo = temp[1];
var CommandThree = temp.slice(2).join(" ");
// lets process the messages and send to users
if((Message) != "") {
// START COMMANDS
// Do join/leave msg disable--------------------------------------------------------------------
if((CommandOne) == "/jpenable" || (CommandOne) == "!jpenable"){
JoinLeaveMsg = "1";
Msg ='***Join/Part message has been Enabled!';
sendMsgToAll(Msg)
MessageString ="";
}
// Do join/leave msg enable--------------------------------------------------------------------
if((CommandOne) == "/jpdisable" || (CommandOne) == "!jpdisable"){
JoinLeaveMsg = "0";
Msg ='***Join/Part message has been Disabled!';
sendMsgToAll(Msg)
MessageString ="";
}
// END COMMANDS
if ((Message).length < maxLength) {
wss.clients.forEach(function e(client) {
client.send(JSON.stringify(
{
name: ConnectedUser,
message: Message
}
));
console.log("Sent: "+ConnectedUser+" "+Message);
});
}else{
wss.clients.forEach(function e(client) {
if(client === ws)
client.send(JSON.stringify(
{
name: '***Server***',
message: "*** Your message exceeds "+maxLength+" characters!"
}
));
});
};
}else{
// dont process if empty line entered
};
}
}
// END INPUT DATA
})
ws.on('close', function(message) {
if(ws.personName){
memberLeftChatMsg(ws);
}
ws.close();
//console.log("Client Disconnected");
});
// END CONNECT
})
server.listen(port, function() {
console.log(`Server is listening on ${port}!`)
})
// FUNCTIONS
// complete Send Message To All
function sendMsgToAll(Msg){
wss.clients.forEach(function e(client) {
client.send(JSON.stringify(
{
name: "Server",
message: Msg
}
));
});
};
// complete
function memberJoinedChatMsg(ws, ConnectingUser) {
if(JoinLeaveMsg != "0"){
wss.clients.forEach(function e(client) {
client.send(JSON.stringify(
{
name: "***Server***",
message: "🟢 <<b>"+ConnectingUser+"</b>> has entered chat!"
}
));
});
}
};
// complete
function memberLeftChatMsg(ws) {
if(JoinLeaveMsg != "0"){
wss.clients.forEach(function e(client) {
client.send(JSON.stringify(
{
name: "***Server***",
message: "🔴 <<b>"+ws.personName+"</b>> has left chat!"
}
));
});
}
};
I also have Dompurify installed using npm to help prevent entities being posted. Remember to open the port in your firewall or change the port number in the script. If you need the client side script including the html, .css let me know, I can upload those too :)
CLIENT SCRIPT:
(function() {
const sendBtn = document.querySelector('#send');
const messages = document.querySelector('#messages');
const messageBox = document.querySelector('#messageBox');
var ws;
var text = "Server: Server Offline!";
var sName = name;
function updateChat(element) {
var name = element[0];
var message = element[1];
const now = new Date();
const tDate = now.toDateString();
const date = new Date(now);
const currentDate = date.toLocaleTimeString();
if(sName == name){
$('.responsive-html5-chat' + ' div.messages').append( '<div class="message"><div class="myMessage"><p>' + message + "</p><date>" + name + " " + currentDate + "</date></div></div>" );
}else{
$('.responsive-html5-chat' + ' div.messages').append( '<div class="message"><div class="fromThem"><p>' + message + "</p><date>" + currentDate + " " + name + "</date></div></div>" );
}
setTimeout(function () { $('.responsive-html5-chat' + ' > span').addClass("spinner"); }, 100);
setTimeout(function () { $('.responsive-html5-chat' + ' > span').removeClass("spinner"); }, 2000);
$(".messages").scrollTop(function() { return this.scrollHeight; });
}
function responsiveChat(element) {
$(element).html('<form class="chat"><span></span><div class="messages"></div><input type="text" id="msg" placeholder="Your message" autocomplete="off"><input id="send" type="submit" value="Send"></form>');
}
responsiveChat('.responsive-html5-chat');
function init() {
if (ws) {
ws.onerror = ws.onopen = ws.onclose = null;
ws.close();
}
ws = new WebSocket('wss://MyDomain.com:1441');
ws.onopen = function() {
if(name) {
ws.send(JSON.stringify({
type: "name",
data: name
}));
}else{
const dat = ['', 'Please Login to chat!'];
updateChat(dat);
ws = null;
return ;
}
}
// START RECIEVED FROM SERVER
ws.onmessage = function(event){
var json = JSON.parse(event.data);
var Name = json.name;
var Message = json.message;
if(name) {
if (Name === "***Server***"){
const dat = ['***Server***', Message];
updateChat(dat);
}else if(Name === "welcome" && name != '') {
Message = 'Hi ' + name + ' ' + Message;
const dat = ['', Message];
updateChat(dat);
}else{
const dat = [Name, Message];
updateChat(dat);
}
}
}
// END RECIEVED FROM SERVER
ws.onclose = function(event) {
if (event.wasClean) {
ws = null;
} else {
const dat = ['', 'Server Offline!'];
updateChat(dat);
ws = null;
}
};
}
// START SEND TO SERVER
send.onclick = function (event){
event.preventDefault();
if(name) {
if (!ws) {
const dat = ['', 'You are not connected... :('];
updateChat(dat);
ws = null;
return ;
}
var messages = document.getElementById("msg").value;
document.getElementById("msg").value = ''; // empty msg box
ws.send(JSON.stringify({
type: "message",
data: name,
message: messages
}));
}else{
const dat = ['', 'Please Login to chat!'];
updateChat(dat);
ws = null;
return ;
}
};
init();
})();
I am developing an office 365 word web addin, wherein I need to upload the currently opened document to my server. For which I am trying to get the file data using following code.
The method getSliceAsync() is returning only first slice of data.
On debugging it gives "Addin Error: Sorry, we had to restart because this addin wasn't responding" while getting second slice.
I am using this link for reference : [https://learn.microsoft.com/en-us/office/dev/add-ins/word/get-the-whole-document-from-an-add-in-for-word][1]
Here is my code:
Office.context.document.getFileAsync(Office.FileType.Compressed, { sliceSize: 65536 }, function (result) {
if (result.status == "succeeded") {
// If the getFileAsync call succeeded, then result.value will return a valid File Object
var myFile = result.value;
var filename1 = myFile.name;
console.log(filename1);
var sliceCount = myFile.sliceCount;
var slicesReceived = 0, isAllSlicesSuccess = true, docdataSlices = [];
// document.getElementById("result").innerText = "File size:" + myFile.size + "#Slices: " + sliceCount;
console.log(" File size:" + myFile.size + " #Slices: " + sliceCount, "");
makeProgress(20);
// Iterate over the file slices
for (var i = 0; i < sliceCount && isAllSlicesSuccess; i++) {
var diffPercent = ((i / sliceCount) * 100);
myFile.getSliceAsync(i, function (sliceResult) {
if (sliceResult.status == "succeeded") {
if (!isAllSlicesSuccess) { // Some slice has failed to get, no need to continue
console.log("Error", "One slice failed to get");
return;
console.log(sliceResult);
}
console.log('sliceResult', sliceResult);
console.log("Success", "i: " + i);
console.log("++slicesReceived ",slicesReceived );
console.log(" sliceCount",sliceCount );
console.log("++slicesReceived == sliceCount",slicesReceived == sliceCount);
// One chunk was got, store it in a temporal array
// ++slicesReceived;
// or you can do something with the chunk, such as sent it to a third party server
docdataSlices[sliceResult.value.index] = sliceResult.value.data;
if (++slicesReceived == sliceCount) {
getAllSlicesTime = Date.now();
var performance = (getAllSlicesTime - startTime) / 1000.0;
console.log("Success", "All slices has been get, Seconds: " + performance);
// All slices have been received
myFile.closeAsync(function (closeRes) {
if (closeRes.status == "succeeded") {
console.log("Close Success", "Success");
// DUClick();
}
else {
console.log("Close Error", closeRes.error.message);
}
});
onGetAllSlicesSucceeded(docdataSlices, false);
}
}
else {
isAllSlicesSuccess = false;
myFile.closeAsync(function (closeRes) {
if (closeRes.status == "succeeded") {
console.log("Close Success", "Success");
// DUClick();
}
else {
console.log("Close Error", closeRes.error.message);
}
});
console.log("Get Slice Error:", sliceResult.error.message);
}
});
}
}
else {
getFileTime = Date.now();
var performance = (getFileTime - startTime) / 1000.0;
console.log('Get File Error:', "Seconds: " + performance + " " + result.error.message);
}
});
Please suggest! Thanks in advance!
[1]: https://learn.microsoft.com/en-us/office/dev/add-ins/word/get-the-whole-document-from-an-add-in-for-word
I have a script that is working fine but can take a lot of time to complete.
This is a javascript document and runs several functions.
This script runs within InDesign and is javascript based. The ExtendScript Toolkit provides several demoscripts and one of them is SnpCreateProgressBar.jsx.
Now I want to add the progressbar to my current script but I'm not entirely sure how to do this.
Without posting the entire code here I'll do a function. This is repeated throughout the script.
var myDoc = app.activeDocument;
var myTables = myDoc.stories.everyItem().tables.everyItem();
var myTableElements = myTables.getElements();
function basicSearchReplace(findWhat, changeTo){
app.findGrepPreferences = app.changeGrepPreferences = null;
app.findChangeGrepOptions = NothingEnum.nothing;
app.findGrepPreferences.findWhat = findWhat;
app.changeGrepPreferences.changeTo = changeTo;
myDoc.changeGrep();
}
basicSearchReplace ('^~8 ', '~8\\t');
basicSearchReplace ('^·( |\\t)', '~8\\t');
The SnpCreateProgressBar.jsx can be found here
Maybe there is another extendscript way to create a progress bar?
--- Small Update ---
So after some Googeling and testing I came up with :
function SnpCreateProgressBar ()
{
this.windowRef = null;
}
SnpCreateProgressBar.prototype.run = function() {
var win = new Window("palette", "SnpCreateProgressBar", [150, 150, 600, 260]);
win.pnl = win.add("panel", [10, 10, 440, 100], "Script Progress");
win.pnl.progBar = win.pnl.add("progressbar", [20, 35, 410, 60], 0, 100);
win.pnl.progBarLabel = win.pnl.add("statictext", [20, 20, 320, 35], "0%");
win.show();
while(win.pnl.progBar.value < win.pnl.progBar.maxvalue)
{
// this is what causes the progress bar increase its progress
win.pnl.progBar.value++;
win.pnl.progBarLabel.text = win.pnl.progBar.value+"%";
$.sleep(10);
}
alert('Done!');
win.close();
};
if(typeof(SnpCreateProgressBar_unitTest) == "undefined") {
new SnpCreateProgressBar().run();
}
Now I don't think I fully understand.
If I place my "to-run" code in the while loop it just executes that and runs the process bar at the end... Same goes for the if-loop at the bottom
What am I not understanding?
See this ProgressBar implementation. I use it all the time :
https://github.com/indiscripts/extendscript/blob/master/scriptui/ProgressBar.jsx
/*******************************************************************************
Name: ProgressBar
Desc: Simple progress bar.
Path: /inc/progress.lib.jsxinc
Require: ---
Encoding: ÛȚF8
Kind: Constructor
API: show()=reset() msg() hit() hitValue() hide() close()
DOM-access: NO (ScriptUI)
Todo: Does not work in Mac El Capitan
Created: 141112 (YYMMDD)
Modified: 160228 (YYMMDD)
*******************************************************************************/
$.hasOwnProperty('ProgressBar')||(function(H/*OST*/,S/*ELF*/,I/*NNER*/)
{
H[S] = function ProgressBar(/*str*/title,/*uint*/width,/*uint*/height)
{
(60<=(width||0))||(width=340);
(40<=(height||0))||(height=60);
var H = 22,
Y = (3*height-2*H)>>2,
W = new Window('palette', ' '+title, [0,0,width,height]),
P = W.add('progressbar', { x:20, y:height>>2, width:width-40, height:12 }, 0,100),
T = W.add('statictext' , { x:0, y:Y, width:width, height:H }),
__ = function(a,b){ return localize.apply(null,a.concat(b)) };
this.pattern = ['%1'];
W.center();
// ---
// API
// ---
this.msg = function(/*str*/s, v)
// ---------------------------------
{
s && (T.location = [(width-T.graphics.measureString(s)[0])>>1, Y]);
T.text = s;
W.update();
};
this.show = this.reset = function(/*str*/s, /*uint*/v)
// ---------------------------------
{
if( s && s != localize(s,1,2,3,4,5,6,7,8,9) )
{
this.pattern[0] = s;
s = __(this.pattern, [].slice.call(arguments,2));
}
else
{
this.pattern[0] = '%1';
}
P.value = 0;
P.maxvalue = v||0;
P.visible = !!v;
this.msg(s);
W.show();
W.update();
};
this.hit = function(x)
// ---------------------------------
{
++P.value;
('undefined' != typeof x) && this.msg(__(this.pattern, [].slice.call(arguments,0)));
W.update();
};
this.hitValue = function(v,x)
// ---------------------------------
{
P.value = v;
('undefined' != typeof x) && this.msg(__(this.pattern, [].slice.call(arguments,1)));
W.update();
};
this.hide = function()
// ---------------------------------
{
W.hide();
};
this.close = function()
// ---------------------------------
{
W.close();
};
};
})($,{toString:function(){return 'ProgressBar'}},{});
Sample code:
//------------------------------------------------
// SAMPLE CODE
//------------------------------------------------
(function()
{
var PB = new $.ProgressBar("Script Title",350,100),
i, vMax;
// Quick process
// ---
PB.show("Processing quickly... %1 / 500", vMax=500, i=0);
for( ; i < vMax ; $.sleep(8), PB.hit(++i) );
PB.reset("Wait for 800 ms...");
$.sleep(800);
// Slow process
// ---
PB.reset("And now slowly (%1%) | Stage %2", vMax=13, 0, i=0);
for( ; i < vMax ; ++i, PB.hit((100*(i/vMax)).toFixed(2), i), $.sleep(400+200*(.5-Math.random())) );
$.sleep(500);
PB.msg("The job is done.");
$.sleep(1500);
// Quit
// ---
PB.close();
})();
I'm new to node.js and working my way through examples of the 'smashing node.js' book. In the websockets chapter I'm struggling to get this example to work. Forgive me it's a really simple error! I'm confused that why couldn't I see the cursor even using the author's code? And I downloaded the source code from Github.
Code is below: (firstly server.js file):
var express = require('express')
, wsio = require('websocket.io')
/**
* Create express app.
*/
var app = express.createServer();
/**
* Attach websocket server.
*/
var ws = wsio.attach(app);
/**
* Serve our code
*/
app.use(express.static('public'))
/**
* Listening on connections
*/
var positions = {}
, total = 0
ws.on('connection', function (socket) {
// we give the socket an id
socket.id = ++total;
// we send the positions of everyone else
socket.send(JSON.stringify(positions));
socket.on('message', function (msg) {
try {
var pos = JSON.parse(msg);
} catch (e) {
return;
}
positions[socket.id] = pos;
broadcast(JSON.stringify({ type: 'position', pos: pos, id: socket.id }));
});
socket.on('close', function () {
delete positions[socket.id];
broadcast(JSON.stringify({ type: 'disconnect', id: socket.id }));
});
function broadcast (msg) {
for (var i = 0, l = ws.clients; i < l; i++) {
// we avoid sending a message to the same socket that broadcasts
if (socket.id != ws.clients[i].id) {
// we call `send` on the other clients
ws.clients[i].send(msg);
}
}
}
});
/**
* Listen
*/
app.listen(3000);
Secondly the script contents of the ./public/index.html file:
<!doctype html>
<html>
<head>
<title>WebSocket cursors</title>
<script src="onload">
window.onload = function () {
var ws = new WebSocket('ws://localhost:3000');
ws.onopen = function () {
document.onmousemove = function (ev) {
ws.send(JSON.stringify({ x: ev.clientX, y: ev.clientY }));
}
}
ws.onmessage = function (msg) {
var obj = JSON.parse(msg);
// the first message is the position of all existing cursors
if (initialized) {
initialized = true;
for (var id in obj) {
move(id, obj[i]);
}
} else {
// other messages can either be a position change or
// a disconnection
if ('disconnect' == obj.type) {
remove(obj.id);
} else {
move(obj.id, obj.pos);
}
}
}
function move (id, pos) {
var cursor = document.getElementById('cursor-' + id);
if (!cursor) {
cursor = document.createElement('img');
cursor.src = '/cursor.png';
cursor.style.position = 'absolute';
document.body.appendChild(cursor);
}
cursor.style.left = pos.x + 'px';
cursor.style.top = pos.y + 'px';
}
function remove (id) {
var cursor = document.getElementById('cursor-' + id);
cursor.parentNode.removeChild(cursor);
}
}
</script>
</head>
<body>
<h1>WebSocket cursors</h1>
</body>
</html>
I changed the express framework from version 2.x.x to the newest version and I updated my websocket.io. Then Rewrited my codes. Now I can run it successfully.
Here's my codes:
server.js:
var express = require('express'),
wsio = require('websocket.io'),
port = 3000,
app = express(),
server = app.listen(port, function() {
console.log('server listening on port ' + port);
});
app.use(express.static('public'))
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
var ws = wsio.attach(server),
positions = {},
total = 0;
ws.on('connection', function(socket) {
socket.id = ++total;
socket.send(JSON.stringify(positions));
socket.on('message', function(msg) {
try {
var pos = JSON.parse(msg);
} catch (e) {
return;
}
positions[socket.id] = pos;
broadcast(JSON.stringify({
type: 'position',
pos: pos,
id: socket.id
}));
});
socket.on('close', function() {
delete positions[socket.id];
broadcast(JSON.stringify({
type: 'disconnect',
id: socket.id
}));
});
function broadcast(msg) {
for (var i = 0, l = ws.clients.length; i < l; i++) {
if (ws.clients[i] && socket.id != ws.clients[i].id) {
ws.clients[i].send(msg);
}
}
}
});
And index.html:
<!doctype html>
<html>
<head>
<title>WebSocket cursors</title>
<script>
window.onload = function() {
var ws = new WebSocket('ws://localhost:3000');
ws.onopen = function() {
document.onmousemove = function(ev) {
ws.send(JSON.stringify({
x: ev.clientX,
y: ev.clientY
}));
}
}
ws.onmessage = function(msg) {
var obj = JSON.parse(msg.data),
initialized = (obj.type) ? true : false;
if (!initialized) {
initialized = true;
for (var id in obj) {
move(id, obj[id]);
}
} else {
if ('disconnect' == obj.type) {
remove(obj.id);
} else {
move(obj.id, obj.pos);
}
}
}
function move(id, pos) {
var cursor = document.getElementById('cursor-' + id);
if (!cursor) {
cursor = document.createElement('img');
cursor.src = '/cursor.png';
cursor.id = 'cursor-' + id;
cursor.style.position = 'absolute';
document.body.appendChild(cursor);
}
cursor.style.left = pos.x + 'px';
cursor.style.top = pos.y + 'px';
}
function remove(id) {
var cursor = document.getElementById('cursor-' + id);
if (cursor) cursor.parentNode.removeChild(cursor);
}
}
</script>
</head>
<body>
<h1>WebSocket cursors</h1>
</body>
</html>
I want to record the audio output from a simple drum sequencer and export it for download as a wav file. I have a live link to my current attempt at this implementation attempt.
The sum output of the sequencer is routed to the variable finalMixNode
yet setting this as the input for the recorder.js doesn't work. I think it may be a problem with the audio context but I can't figure it out. I successfully created a oscillator and recorded its output but I can't extend this to the sequencer.
Here is the main js code in which I am trying to record the output. I'm hoping someone will see what I am missing.
//audio node variables
var context;
var convolver;
var compressor;
var masterGainNode;
var effectLevelNode;
var lowPassFilterNode;
var noteTime;
var startTime;
var lastDrawTime = -1;
var LOOP_LENGTH = 16;
var rhythmIndex = 0;
var timeoutId;
var testBuffer = null;
var currentKit = null;
var reverbImpulseResponse = null;
var tempo = 120;
var TEMPO_MAX = 200;
var TEMPO_MIN = 40;
var TEMPO_STEP = 4;
if (window.hasOwnProperty('AudioContext') && !window.hasOwnProperty('webkitAudioContext')) {
window.webkitAudioContext = AudioContext;
}
$(function() {
init();
toggleSelectedListener();
playPauseListener();
lowPassFilterListener();
reverbListener();
createLowPassFilterSliders();
initializeTempo();
changeTempoListener();
});
function createLowPassFilterSliders() {
$("#freq-slider").slider({
value: 1,
min: 0,
max: 1,
step: 0.01,
disabled: true,
slide: changeFrequency
});
$("#quality-slider").slider({
value: 0,
min: 0,
max: 1,
step: 0.01,
disabled: true,
slide: changeQuality
});
}
function lowPassFilterListener() {
$('#lpf').click(function() {
$(this).toggleClass("active");
$(this).blur();
if ($(this).hasClass("btn-default")) {
$(this).removeClass("btn-default");
$(this).addClass("btn-warning");
lowPassFilterNode.active = true;
$("#freq-slider,#quality-slider").slider( "option", "disabled", false );
}
else {
$(this).addClass("btn-default");
$(this).removeClass("btn-warning");
lowPassFilterNode.active = false;
$("#freq-slider,#quality-slider").slider( "option", "disabled", true );
}
})
}
function reverbListener() {
$("#reverb").click(function() {
$(this).toggleClass("active");
$(this).blur();
if ($(this).hasClass("btn-default")) {
$(this).removeClass("btn-default");
$(this).addClass("btn-warning");
convolver.active = true;
}
else {
$(this).addClass("btn-default");
$(this).removeClass("btn-warning");
convolver.active = false;
}
})
}
function changeFrequency(event, ui) {
var minValue = 40;
var maxValue = context.sampleRate / 2;
var numberOfOctaves = Math.log(maxValue / minValue) / Math.LN2;
var multiplier = Math.pow(2, numberOfOctaves * (ui.value - 1.0));
lowPassFilterNode.frequency.value = maxValue * multiplier;
}
function changeQuality(event, ui) {
//30 is the quality multiplier, for now.
lowPassFilterNode.Q.value = ui.value * 30;
}
function playPauseListener() {
$('#play-pause').click(function() {
var $span = $(this).children("span");
if($span.hasClass('glyphicon-play')) {
$span.removeClass('glyphicon-play');
$span.addClass('glyphicon-pause');
handlePlay();
}
else {
$span.addClass('glyphicon-play');
$span.removeClass('glyphicon-pause');
handleStop();
}
});
}
function toggleSelectedListener() {
$('.pad').click(function() {
$(this).toggleClass("selected");
});
}
function init() {
initializeAudioNodes();
loadKits();
loadImpulseResponses();
}
function initializeAudioNodes() {
context = new webkitAudioContext();
var finalMixNode;
if (context.createDynamicsCompressor) {
// Create a dynamics compressor to sweeten the overall mix.
compressor = context.createDynamicsCompressor();
compressor.connect(context.destination);
finalMixNode = compressor;
} else {
// No compressor available in this implementation.
finalMixNode = context.destination;
}
// Create master volume.
// for now, the master volume is static, but in the future there will be a slider
masterGainNode = context.createGain();
masterGainNode.gain.value = 0.7; // reduce overall volume to avoid clipping
masterGainNode.connect(finalMixNode);
//connect all sounds to masterGainNode to play them
//don't need this for now, no wet dry mix for effects
// // Create effect volume.
// effectLevelNode = context.createGain();
// effectLevelNode.gain.value = 1.0; // effect level slider controls this
// effectLevelNode.connect(masterGainNode);
// Create convolver for effect
convolver = context.createConvolver();
convolver.active = false;
// convolver.connect(effectLevelNode);
//Create Low Pass Filter
lowPassFilterNode = context.createBiquadFilter();
//this is for backwards compatibility, the type used to be an integer
lowPassFilterNode.type = (typeof lowPassFilterNode.type === 'string') ? 'lowpass' : 0; // LOWPASS
//default value is max cutoff, or passing all frequencies
lowPassFilterNode.frequency.value = context.sampleRate / 2;
lowPassFilterNode.connect(masterGainNode);
lowPassFilterNode.active = false;
}
function loadKits() {
//name must be same as path
var kit = new Kit("TR808");
kit.load();
//TODO: figure out how to test if a kit is loaded
currentKit = kit;
}
function loadImpulseResponses() {
reverbImpulseResponse = new ImpulseResponse("sounds/impulse- responses/matrix-reverb2.wav");
reverbImpulseResponse.load();
}
//TODO delete this
function loadTestBuffer() {
var request = new XMLHttpRequest();
var url = "http://www.freesound.org/data/previews/102/102130_1721044-lq.mp3";
request.open("GET", url, true);
request.responseType = "arraybuffer";
request.onload = function() {
context.decodeAudioData(
request.response,
function(buffer) {
testBuffer = buffer;
},
function(buffer) {
console.log("Error decoding drum samples!");
}
);
}
request.send();
}
//TODO delete this
function sequencePads() {
$('.pad.selected').each(function() {
$('.pad').removeClass("selected");
$(this).addClass("selected");
});
}
function playNote(buffer, noteTime) {
var voice = context.createBufferSource();
voice.buffer = buffer;
var currentLastNode = masterGainNode;
if (lowPassFilterNode.active) {
lowPassFilterNode.connect(currentLastNode);
currentLastNode = lowPassFilterNode;
}
if (convolver.active) {
convolver.buffer = reverbImpulseResponse.buffer;
convolver.connect(currentLastNode);
currentLastNode = convolver;
}
voice.connect(currentLastNode);
voice.start(noteTime);
}
function schedule() {
var currentTime = context.currentTime;
// The sequence starts at startTime, so normalize currentTime so that it's 0 at the start of the sequence.
currentTime -= startTime;
while (noteTime < currentTime + 0.200) {
var contextPlayTime = noteTime + startTime;
var $currentPads = $(".column_" + rhythmIndex);
$currentPads.each(function() {
if ($(this).hasClass("selected")) {
var instrumentName = $(this).parents().data("instrument");
switch (instrumentName) {
case "kick":
playNote(currentKit.kickBuffer, contextPlayTime);
break;
case "snare":
playNote(currentKit.snareBuffer, contextPlayTime);
break;
case "hihat":
playNote(currentKit.hihatBuffer, contextPlayTime);
break;
case "tomhi":
playNote(currentKit.tomhiBuffer, contextPlayTime);
break;
case "tommid":
playNote(currentKit.tommidBuffer, contextPlayTime);
break;
case "tomlow":
playNote(currentKit.tomlowBuffer, contextPlayTime);
break;
case "cl":
playNote(currentKit.clBuffer, contextPlayTime);
break;
case "cb":
playNote(currentKit.cbBuffer, contextPlayTime);
break;
case "cp":
playNote(currentKit.cpBuffer, contextPlayTime);
break;
case "cy":
playNote(currentKit.cyBuffer, contextPlayTime);
break;
case "rs":
playNote(currentKit.rsBuffer, contextPlayTime);
break;
}
//play the buffer
//store a data element in the row that tells you what instrument
}
});
if (noteTime != lastDrawTime) {
lastDrawTime = noteTime;
drawPlayhead(rhythmIndex);
}
advanceNote();
}
timeoutId = requestAnimationFrame(schedule)
}
function drawPlayhead(xindex) {
var lastIndex = (xindex + LOOP_LENGTH - 1) % LOOP_LENGTH;
//can change this to class selector to select a column
var $newRows = $('.column_' + xindex);
var $oldRows = $('.column_' + lastIndex);
$newRows.addClass("playing");
$oldRows.removeClass("playing");
}
function advanceNote() {
// Advance time by a 16th note...
// var secondsPerBeat = 60.0 / theBeat.tempo;
//TODO CHANGE TEMPO HERE, convert to float
tempo = Number($("#tempo-input").val());
var secondsPerBeat = 60.0 / tempo;
rhythmIndex++;
if (rhythmIndex == LOOP_LENGTH) {
rhythmIndex = 0;
}
//0.25 because each square is a 16th note
noteTime += 0.25 * secondsPerBeat
// if (rhythmIndex % 2) {
// noteTime += (0.25 + kMaxSwing * theBeat.swingFactor) * secondsPerBeat;
// } else {
// noteTime += (0.25 - kMaxSwing * theBeat.swingFactor) * secondsPerBeat;
// }
}
function handlePlay(event) {
rhythmIndex = 0;
noteTime = 0.0;
startTime = context.currentTime + 0.005;
schedule();
}
function handleStop(event) {
cancelAnimationFrame(timeoutId);
$(".pad").removeClass("playing");
}
function initializeTempo() {
$("#tempo-input").val(tempo);
}
function changeTempoListener() {
$("#increase-tempo").click(function() {
if (tempo < TEMPO_MAX) {
tempo += TEMPO_STEP;
$("#tempo-input").val(tempo);
}
});
$("#decrease-tempo").click(function() {
if (tempo > TEMPO_MIN) {
tempo -= TEMPO_STEP;
$("#tempo-input").val(tempo);
}
});
}
function __log(e, data) {
log.innerHTML += "\n" + e + " " + (data || '');
}
var audio_context;
var recorder;
function startUserMedia() {
var input = finalMixNode;
__log('Media stream created.');
input.start();
__log('Input connected to audio context destination.');
recorder = new Recorder(input);
__log('Recorder initialised.');
}
function startRecording(button) {
recorder && recorder.record();
button.disabled = true;
button.nextElementSibling.disabled = false;
__log('Recording...');
}
function stopRecording(button) {
recorder && recorder.stop();
button.disabled = true;
button.previousElementSibling.disabled = false;
__log('Stopped recording.');
// create WAV download link using audio data blob
createDownloadLink();
recorder.clear();
}
function createDownloadLink() {
recorder && recorder.exportWAV(function(blob) {
var url = URL.createObjectURL(blob);
var li = document.createElement('li');
var au = document.createElement('audio');
var hf = document.createElement('a');
au.controls = true;
au.src = url;
hf.href = url;
hf.download = new Date().toISOString() + '.wav';
hf.innerHTML = hf.download;
li.appendChild(au);
li.appendChild(hf);
recordingslist.appendChild(li);
});
}
window.onload = function init() {
try {
// webkit shim
window.AudioContext = window.AudioContext || window.webkitAudioContext;
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
window.URL = window.URL || window.webkitURL;
// audio_context = new AudioContext;
__log('Audio context set up.');
} catch (e) {
alert('No web audio support in this browser!');
}
startUserMedia();
};
Your finalMixNode is scoped into the initializeAudioNodes() function, therefore it is undefined when you call it from startUserMedia().
Also, this variable is either a dynamicCompressor node or the AudioContext's destination.
Recorderjs needs a node with an output (which AudioDestinationNode doesn't have currently1 ) so make sure to construct your recorder with the final compressor node (or a final gainNode)
Executing this in my js console from your page does work :
var recorder = new Recorder(compressor);
1 Thanks #padenot for noticing me it's being discussed here