HTML5 Canvas ‘strangeness’

I was experimenting with the Canvas tag, and the code below worked great on Firefox, but would not on Safari or Chrome:

[code]

function draw(img) {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var image = new Image();
image.src = "http://localhost:3000" + img;
var context = canvas.getContext("2d");
context.drawImage(image,0,0);
}
}
[/code]

Quite baffling. No errors on the javascript console either. It took me a little while to figure out that the problem.

The problem is that the browser may load images simultaneously while executing your javascript If the image load is not complete, well, your image does not display properly, and as far as the browser is concerned, there is no problem. (interesting how firefox 4 beta worked every time)

The solution? Attach an event listener,

[code]

window.addEventListener("load",draw,true);

function draw(img) {
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var image = new Image();
image.src = "http://localhost:3000" + img;
var context = canvas.getContext("2d");
image.onload = function () {
context.drawImage(image,0,0);
}
[/code]

Notice the addition of the eventlistener and the onload. That fixed it.

using ImageMagick+ paperclip with rails3 on MacOS


  • Download Imagemagick binaries from here

  • open a terminal and run ‘tax xvzf ImageMagick-x.x-x’

  • You will now have the untarred file, but not in the right location. I suggest installing it in /usr/local/imagemagick. So from your shell, do ‘sudo mkdir /usr/local/imagemagick’. This assumes that you are in the sudoers list

  • You will need to update your path so that the binaries are picked up. If you are using bash, go to your home directory and open .bashrc, and add this line:


  • [code]
    export PATH=/usr/local/imagemagick/bin:${PATH}
    [/code]

  • gem install paperclip

  • create paperclip.rb in config/environments of your rails project. Add these lines:
  • [code]
    Paperclip.options[:command_path] = "DYLD_LIBRARY_PATH=’/usr/local/imagemagick/lib’ /Users/sram/Downloads/ImageMagick-6.6.5/bin"
    Paperclip.options[:magick_home] = ‘/usr/local/imagemagick’

    [/code]

  • Restart your server, you should be good to go. Use Jim Neath’s excellent tutorial to use paperclip

Fun with websockets, Node.js and jQuery

Websockets have the potential to make a big difference to loading on webservers, and improve interactivity characteristics of client side.

Coupled with Redis for persistence and Node.js for a fast web server can make a huge difference to the performance of your web server. I will focus on websockets in this tutorial: Redis and Node.js will be covered later, and there are lots of good sources for them on the web.

I worked on a little experiment to see how Node.js & websockets work. If you are just getting started with websockets, this tutorial might help you out.

Make sure to use a browser that supports websockets. Firefox & Opera have removed support because of a security hole. I have tested with Chrome.

Client Setup
Here is some really simple HTML to build the demo:

[code lang="js"]
<!DOCTYPE html>
<html>
<head>
<title>Websocket test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
</head>

<body>
<div class="dvStory">
<form id="fmStory">
<textarea id="taStory" rows="2" cols="20"></textarea>
<input type="submit" id="buStory" name="submit changes"/>
</form>
</div>
[/code]

This will give you a text area and a submit button.

Let’s finish setting up the client. We’ll add some javascript to set up websockets

Add Javascript
We’ll set up some variables to use in javascript. The websocket code is really simple to setup and use


[code lang="js"]
<script type="text/javascript">
alert ("socket is null");
var fm = $("#fmStory");
var ta = $("#taStory");

function doOpen() {
var s= new WebSocket('ws://localhost:8081');
alert("socket open");
s.onopen = function () {
//s.send ("ok I am warmed up");
};
return s;
}

var socket = doOpen();

function sendData() {
// alert ("ta changed");
socket.send ( ta.val() );
}
[/code]

doOpen() creates a new websocket, running at localhost port 8081, and sends a hello message to the server when the socket is opened. Pretty simple API. The variable socket gets initialized, and sendData() is called every time the client needs to receive data. Websockets are bidirectional, of course, so unlike regular HTTP connections, they can receive server initiated data, which needed other methods like Comet earlier (or usage of polling). We’ll look at how to recieve server data next.


[code lang="js"]
ta.change (function (event) {
sendData();
});
$('#buStory').click (function () {
alert ("click event");
socket.send (ta.val());
return false;
});
socket.onmessage = function(event) {
//alert ("got message" + event.data);
ta.val(event.data);
};

</script>
</body>
</html>
[/code]

sendData gets called when a click even or a change event occurs. If you are not familiar with jQuery, just know that you can register for events and react to them, which is what ta.change() and $(‘#buStory’).click() do.
Finally, socket.onmessage is what gets executed when the server sends a message to the client. We just update the text area with the message pushed by the server.

This is the way the code works: Any client connected to the server will send a message to the server when a change event or a submit takes place. The Server will turn around and echo the change to all connected clients. So to try this out, have multiple windows open connected to the server.

Save the code in a file, client.html. You will be opening localhost:8081/client.html to try this out.

The Server Code
Download node.js and a nice library to make websocket usage more convenient, https://github.com/miksago/node-websocket-server

Once you have installed it, type up the following code

get some libraries


[code lang="js"]
var sys = require("sys"),
path = require("path"),
http = require ("http"),
url = require ("url"),
fs = require("fs"),
debug = require("util"),
events = require("events");
// Library https://github.com/miksago/node-websocket-server
var websocket = require('../lib/ws/server');
<!--formatted-->
[/code]

Create the webserver

[code lang="js"]
/ create web socket server
var server = websocket.createServer();
// listen on port 8081
server.listen(8081);
[/code]

Next, we need a way to have the server return HTML files. This part of the code is taken from the excellent tutorial at tutsplus


[code lang="js"]
function load_static_file(uri, response) {
var filename = path.join(process.cwd(), uri);

path.exists(filename, function(exists) {
if(!exists) {
response.sendHeader(404, {"Content-Type": "text/plain"});
response.write(filename + "404 Not Found\n");
response.close();
return;
}

fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.sendHeader(500, {"Content-Type": "text/plain"});
response.write(err + "\n");
response.close();
return;
}

response.sendHeader(200);
response.write(file, "binary");
response.close();
});
});
}
[/code]

Now, if our node.js server receives a regular HTTP call, we know it is looking for the client file , so we just return it


[code lang="js"]
server.addListener("request", function(req, res) {
var uri = url.parse(req.url).pathname;
load_static_file(uri,res);
});
[/code]

So when the client connects with http://localhost:8081/client.html, the server will just return the HTML.

However, if the connection is a websocket one, here’s the code that gets invoked


[code lang="js"]
server.addListener("connection", function(conn) {
debug.print (" Yo, welcome!");
// when client writes something
conn.addListener("message", function(message) {
debug.print ("yo, got message " + message + "\n");
// iterate thorough all connected clients, and push this message
server.manager.forEach(function(connected_client) {
debug.print ("sending message to" + connected_client);
connected_client.write(JSON.stringify(conn.id + ": " + message));
});
});
});
[/code]

What is happening here? We add a listener, which hangs around waiting for connections. When there is a connection, we wait for a message to come. When a message is received, we iterate over all the connections, and write it to all connected clients. debug.print can be used to debug on the server side.

Thats how simple using websockets is, and combined with node.js, they can be pretty awesome.