How to make a real-time in-browser editor with the HTML5′s contenteditable attribute

Lots of fun here. Some days ago I just read a very cool comment on html5doctor:

Here is a fun example with the contenteditable attribute.

Just paste this data-url to your browser and then edit the title or the style of the whole page

data:text/html,<title contenteditable>Hello World</title> <style contenteditable>head, title, style {display: block;}</style>

Another thing is that you can create a notepad with just one short url:

data:text/html,<html contenteditable></html>

Pretty cool I think.

Cat with eyes shining bright This just made my eyes shine brighter than ever. I think there’s a lot of potential here: do you imagine how many things you could realize with the contenteditable attribute?

For example, you can even do this:

1
2
3
script {
  display: block;
}

The result? A JavaScript in-browser editor.


Can I really build an HTML5 editor in my browser?

Absolutely. This tutorial is focused on how to build a simple but powerful editor, directly within your browser, making it possible to edit your page content in real time. It may sound like a lot of work, but don’t worry: actually it’s easier than it seems, for two main reasons:

  1. The browser already shows content in real time. When you open Firebug on Firefox, Chrome DevTools, Opera Dragonfly, or whatever, and you edit the CSS or JS, the browser automatically re-renders its window.
  2. You don’t need any parser. Again, and unsurprisingly, the browser is already capable to interpret your code.

In fewer words, this means you already have the tools. Just use your imagination to build something awesome.

In this tutorial I won’t talk about everything, but only of the problems I’ve encountered while building an editor, and how to solve them.

Displaying the <script> and <style> tags

This is actually very simple. You only need to match them by CSS, and apply display: block to them. For example:

1
2
3
style, script {
  display: block;
}

However I’d recommend to apply this rule only to the elements that have the contenteditable attribute. You can do this with:

1
2
3
4
[contenteditable] {
  /* will match all elements with contenteditable attribute */
  display: block;
}

How to make it look like real code

Real editors use monospace fonts. We can also make <script> and <style> behave like the <pre> tag. All we need is the following code.

1
2
3
4
style, script {
  font-family: monospace;  /* monospace font */
  white-space: pre;        /* behave like <pre> */
}

You can even install a syntax highlighter like the Google code prettify, if you want.

Make the page title editable

This one is real fun. It’s ridicolously easy to show the title directly in the browser, but pay attention because the <title> tag is inside <head>, that is hidden by default! So you must display the title and the head, as a block:

1
2
3
head, title {
  display: block;
}

Then just make it contenteditable and you’re done.

1
<title contenteditable>The page title</title>

Executing the JavaScript in real time

Now the tricky part. Your scripts actually get executed only the first time, on page load. So the question is, how can we re-execute the JavaScript every time it changes?

Well, I’m sure there are many solutions. Mine is quite straightforward: I dynamically create a new <script> element every time the user adds something new. For the sake of simplicity I’ve created this function:

1
2
3
4
5
6
7
function executeCode() {
  var script = document.createElement("script");
  script.innerHTML = js.innerHTML;
  js.parentNode.insertBefore(script, js);
}
// the code we want to execute is contained here:
var js = document.getElementById('js');

Why I’ve put the js variable outside of the function? You’ll find it out soon.

We need to call the executeCode() function during an event in order make it work properly. I think the onkeyup event will be perfect in this situation: it gets fired as soon as the user has finished typing.

1
2
3
js.onkeyup = function(event) {
  executeCode();
};

However, this approach has a flaw. What if I type, say, alert('foobar')? I won’t see an alert, but… 15 alerts! This because the onkeyup event would get fired 15 times in this case — one for each character. How can we solve this problem?

Again, there can be many solutions. I chose to use window.setTimeout(). My implementation is fairly simple: I just tell the browser to wait 2000 milliseconds (2 seconds) before executing the new code, but if the user modifies the code in the meanwhile, I reset the timer. This is the key to prevent the code getting executed more than once.

Here’s a full example, feel free to copy-paste and try it directly in your browser:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<h1>Sample JavaScript real-time in-browser execution</h1>

<script id="js" style="display: block" contenteditable>
alert('foo'); // edit me!
</script>

<script>
(function() {

  var timer,
      js = document.getElementById('js'),
      delay = 2000;

  js.onkeyup = function(event) {

    if (typeof timer != "undefined") {

      clearTimeout(timer);
      timer = 0;
    }

    timer = setTimeout(executeCode, delay);
  };

 function executeCode() {
    var script = document.createElement("script");
    script.innerHTML = js.innerHTML;
    js.parentNode.insertBefore(script, js);
 }

})();
</script>

It’s your turn now!

I just demonstrated that it’s definitely possible to build an HTML5 editor that works directly in your browser. Imagine a full-featured WYSIWYG in-browser editor: it could potentially improve your productivity, enabling real-time collaboration and a lot more. Your only limit is your imagination.

Need inspiration?

Demo | Download

Git cheat sheet

Git is an awesome tool for developers, but can be a bit hard to grasp at a first glance. Fortunately, the concepts you need to learn to be immediately productive are very few: I’ll briefly illustrate them in this Git cheat sheet.

1. Basics

1
2
3
4
5
6
7
# start a Git repository from scratch
$ git init

# copy an existing repository into the current directory
$ git clone https://github.com/username/repository.git

$ git status  # check current status

2. Snapshotting

1
2
3
4
5
6
7
8
9
10
# Add files to staging area
$ git add filename  # add a single file
$ git add .         # add all files, but not deleted ones
$ git add --all     # add everything

# Stashing takes the current state of the working directory and
# puts it on a stack for later
$ git stash        # add current changes to the stack
$ git stash list   # see what's in the stack
$ git stash apply  # bring back the saved changes

3. Committing

1
2
3
4
5
6
7
$ git commit            # open the text editor (usually vi)
$ git commit -a         # automatically stage modified files
$ git commit -m "foo"   # commit with message "foo"
$ git commit -am "foo"  # both stage files and commit with message "foo"

# View commits log (in a pretty way)
$ git log --oneline --decorate --graph

4. Managing remotes

1
2
3
4
$ git remote add origin https://github.com/user/repo.git
# You can also add your GitHub username and password on the remote URL:
$ git remote add origin https://user:[email protected]/user/repo.git
$ git remote rm origin  # removes the `origin` remote

5. Pushing

1
2
3
4
$ git push -u origin master
# -u here tells git to remember the parameters
# so that next time we can simply run:
$ git push

6. Branching

1
2
3
4
5
$ git checkout -b new_branch
# -b is to checkout and create a branch at the same time.
# This is the same thing as doing:
$ git branch new_branch
$ git checkout new_branch

7. Merging

1
2
3
4
$ git checkout master       # return to master branch
$ git merge --no-ff foobar  # merge `master` branch with `foobar` branch
$ git branch -d foobar      # delete branch locally
$ git push origin :foobar   # delete branch on the origin remote

8. Tagging

1
2
3
$ git tag -a v1.3.37               # tag the HEAD (most recent commit)
$ git tag -a v0.6b f49a23c         # tag the commit with SHA `f49a23c`
$ git tag -a v4.2 -m "jelly bean"  # append a message

That’s all, folks. I know I could have explained much more every single command, but that’s not the point of this article. I just wanted to give you a quick-start pragmatic reference; in fact, these are the commands I personally use more frequently.

Do you think some very useful commands are missing in this cheat sheet? Leave a reply.

  • Update march 5: added tagging.
  • Update april 23: just made some “refactoring” and added git stash.
  • Update dec 3: I’ve updated the “merging” section with the command for deleting the remote branch as well. I’ve also added the --no-ff option, that disables fast-forwarding (reason explained here).

onclick vs addEventListener

What’s the difference between these two lines of code?

1
element.onclick = function() { /* do stuff */ }
1
element.addEventListener('click', function(){ /* do stuff */ }, false);

They apparently do the same thing: listen for the click event and execute a callback function. Nevertheless, they’re not equivalent. If you ever need to choose between the two, this could help you to figure out which one is the best for you.

The main difference is that onclick is just a property, and like all object properties, if you write on more than once, it will be overwritten. With addEventListener() instead, we can simply bind an event handler to the element, and we can call it each time we need it without being worried of any overwritten properties.

In first place I was tempted to keep using onclick, because it’s shorter and looks simpler… and in fact it is. But I don’t recommend using it anymore. It’s just like using inline JavaScript. Using something like <button onclick="doSomething()">that’s inline JavaScript – is highly discouraged nowadays (inline CSS is discouraged too, but that’s another topic).

However, the addEventListener() function, despite it’s the standard, just doesn’t work in old browsers (Internet Explorer below version 9), and this is another big difference. If you need to support these ancient browsers, you should follow the onclick way. But you could also use jQuery (or one of its alternatives): it basically simplifies your work and reduces the differences between browsers, therefore can save you a lot of time.

How to setup OS X 10.8 for Ruby on Rails 3.2

Looks like almost every Rails developer is using OS X as development environment, so in this brief walkthrough I’ll explain you how to prepare your machine for Ruby on Rails development: nothing more, nothing less. I assume you are already running Mac OS X 10.8 Mountain Lion.

Install Command Line Tools for Xcode

Download it from developer.apple.com (you need an Apple ID).

As an alternative you can use osx-gcc-installer or install it via the Xcode GUI.

Install Homebrew

1
$ ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"

Install RVM (Ruby Version Manager)

You can:

  1. Download and install JewelryBox
  2. Or from the command line:
    1
    
    $ curl -L https://get.rvm.io | bash -s stable --ruby
    

Install and configure Git

You can:

  1. Get the latest version from the official website
  2. Or install it via Homebrew:
    1
    
    $ brew install git
    
1
2
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"

Install Ruby via RVM

1
$ rvm install ruby-2.0.0

Install Rails via RubyGem

Notice: you may need to restart your terminal session before installing Rails.

1
$ gem install rails -v 3.2.13

And you’re ready to ride Ruby on Rails! Yee-ha!

Problems? Suggestions? Leave a comment.

101 Web Socket Protocol Handshake: a pragmatic guide

So you want to set up a web socket server, but you don’t know how. Maybe you just landed here after a bunch of Google searches. Well, keep reading: you’re in the right place.

The Web Socket in a nutshell

The new protocol is revolutionizing the whole Internet.

The Web Socket protocol is the new alternative to the very popular HTTP protocol. The logic of the latter is well known: the client requests, the server responds. Request, response. Stop. This is what we call a simplex connection. It worked for decades, but has severe limitations therefore it’s not ideal for rich web applications, which would work better under a persistent connection. We need to serve content in real time; that’s why the new protocol is born.

The WebSocket is awesome, especially if your goal is to build a chat, a VoIP server, or even a RTS game! Sounds good, huh? Let’s see how it works.

Roll your own Web Socket server and client

This guide is focused on the official W3C’s WebSocket API specification for the client part; we’ll use a Node.js WebSocket implementation as the server. If you’re curious on how Node.js works, just check it out: there are tons of resources out there.

Okay, let’s get started with the client: nothing fussy, It’s just a simple HTML page. Call it index.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>WebSocket Client</title>
</head>
<body>
  <h1>WebSocket Client</h1>
  <p>Open the JavaScript console to see the response!</p>
  <form>
    <label for="message">Send a message</label>
    <input id="message" name="message" type="text">
    <button id="send" name="send">Send</button>
  </form>
  <script src="ws_client.js"></script>
</body>
</html>

You may have noticed the script tag:

1
<script src="ws_client.js"></script>

Of course we need a bit of JavaScript in order to make it work, but don’t worry! Initializing a web socket server is just as simple as the following line of code. Create the file ws_client.js and write:

1
var ws = new WebSocket("ws://localhost:1337");

If you’re already familiar with object-oriented programming, you should know we have been built a new instance of the WebSocket object, that’s built-in in all modern browsers. The ws://localhost:1337 part just tells the WebSocket API to initialize a new connection on localhost:1337 using the ws protocol.

Now let’s code some event handlers. I won’t elaborate, they’re self-descriptive:

1
2
3
4
5
6
7
8
9
10
11
12
ws.onopen = function(ev) {
  console.log('Connection opened.');
}
ws.onmessage = function(ev) {
  console.log('Response from server: ' + ev.data);
}
ws.onclose = function(ev) {
  console.log('Connection closed.');
}
ws.onerror = function(ev) {
  console.log('An error occurred. Sorry for that.');
}

Since we want to send a message to the server, we should use the WebSocket.send() function; but it doesn’t have a callback return value, so I’ll define a new function, sendMessage(), that does exactly the same plus logging the message on the console.

1
2
3
4
WebSocket.prototype.sendMessage = function(msg) {
  this.send(msg);
  console.log('Message sent: ' + msg);
}

Finally I get the button to work by attaching an event handler to it:

1
2
3
4
5
6
var sendBtn = document.getElementById('send');
sendBtn.addEventListener('click', function(ev) {
  var message = document.getElementById('message').value;
  ws.sendMessage(message);
  ev.preventDefault();
});

Basically, when we click on the button we send a message to the server. That’s it. You may wonder what does ev.preventDefault() do; it just makes sure that when we click the Send button, the form doesn’t get submitted.


At this stage you should have downloaded and installed Node.js: the procedure is slightly different for every operating system; just make sure to download the right installer.

Node comes with npm, the official package manager, that makes the WebSocket-Node package installation ridiculously easy:

1
$ npm install websocket

This shell command should install the WS implementation for Node.js on your machine. Now open the Node installation folder (if you don’t know where it is and you’re using a UNIX-based operating system, try which node) and create the file that will host our server:

1
2
$ cd ~/local/node
$ touch ws_server.js

Since this file will be executed by Node itself, it must start with the following:

1
#!/usr/bin/env node

Require the WS server and the HTTP protocol APIs:

1
2
var WebSocketServer = require('websocket').server;
var http = require('http');

Then you can define the HTTP server itself:

1
2
3
4
5
var server = http.createServer(function(request, response) {
  console.log('Received request from ' + request.url);
  response.writeHead(404);
  response.end();
});

The server must be listening on a port. I’ve chosen the 1337 port, but it can be almost anything.

1
2
3
server.listen(1337, function() {
  console.log('Server is listening on port 1337.');
});

Our WebSocket server is based on the HTTP server we have just created above, with a bit of security rules:

1
2
3
4
wsServer = new WebSocketServer({
  httpServer: server,
  autoAcceptConnections: false // because security matters
});

The autoAcceptConnections parameter is absolutely necessary here, because we don’t want to allow connections from any source domain! That’s why I wrote a custom function that accepts or discards an incoming remote connection: it accepts only requests from 127.0.0.1 or http://localhost, but you can of course allow any origin you want.

1
2
3
4
5
6
7
8
function isAllowedOrigin(origin) {
  valid_origins = ['http://localhost', '127.0.0.1'];
  if (valid_origins.indexOf(origin) != -1) { // is in array
    console.log('Connection accepted from origin ' + origin);
    return true;
  }
  return false;
}

This way we can easily filter connections based on the origin:

1
2
3
4
5
wsServer.on('request', function(request) {
  var connection = isAllowedOrigin(request.origin) ?
    request.accept() :
    request.reject();
}

How can we check if a client sends us a message? We can do it by using the message event:

1
2
3
connection.on('message', function(message) {
  console.log('Received Message: ' + message.utf8Data);
}

The message must be in UTF-8 format; we must inspect the message.type attribute. If the type is correct, we can process the request and define the response accordingly. Here’s my demonstrative implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
if (message.type === 'utf8') {

  var response = '';

  switch (message.utf8Data) {
    case 'hi':
      response = 'Hey there';
      break;
    case 'hello':
      response = 'Heya!';
      break;
    case 'xyzzy':
      response = 'Nothing happens.';
      break;
    case 'desu':
      response = 'Keep typing, man. Keep typing.';
      break;
    default:
      response = "Hello. Uh... what am I supposed to do with '" +
      message.utf8Data + "'?";
  }
  connection.sendUTF(response);
}

It’s always a good idea to log when the connection starts and gets closed:

1
2
3
4
5
6
7
wsServer.on('connection', function(webSocketConnection) {
  console.log('Connection started.');
});

connection.on('close', function(reasonCode, description) {
  console.log(connection.remoteAddress + ' has been disconnected.');
});

And that’s all. We now have a basic WebSocket server implementation and we’re ready for the handshake.

Establish a connection between server and client

We can now test our brand new WebSocket server. Open the command prompt and start the server with:

1
2
$ node ws_server.js
Server is listening on port 1337.

Finally open the client (index.html) with your favourite browser and try to send a message.

When you send a web socket request as a client, you’ll send an HTTP header like this one:

1
2
3
4
5
GET / HTTP/1.1
Host: localhost:1337
User-Agent: Mozilla/5.0 [...]
Upgrade: websocket
...

And the server will respond something like:

1
2
3
4
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
...

This means you just established a full-duplex connection between the client and the server. If everything went as expected, the console should say something like:

1
Connection accepted from origin: http://localhost

And from this point every message will be logged on the console. Of course you shouldn’t close the console or the server will go down. If you want to close the connection you can both press Ctrl + C or close the browser’s window.


I hope you enjoyed following this guide. You can read the full source code of this tutorial on GitHub, or download it directly. The demo also comes with a file for testing your actual browser support for the WebSocket API.