WebGL backend

This PR implements an online WebGL backend on the IPython notebook.

Most of the JavaScript code is [there](https://github.com/vispy/vispy.js), and minified here (`vispy.min.js`).

### Event loop

I think I have figured out the best way to implement the event loop in the notebook. Everything is triggered from JavaScript exclusively. The reason is that regular WebGL applications have to implement `requestAnimationFrame()` for the event loop. Here is how it works:

* This JS callback function is called at a framerate depending on the screen refresh rate (this is handled by the browser). If the window is hidden or minified, the loop stops automatically (the browser does everything for us).
* When the user moves the mouse and do things in the canvas, events are saved in a JS queue.
* The event loop processes the queue, sends all events to Python, and clears the queue.
* When Python receives the events, it processes them through Vispy, and a list of GLIR commands is generated and sent back to the browser. These events are pushed into a GLIR queue in JS.
* In the JS event loop, if the GLIR queue is not empty, the events are processed by the WebGL backend.

This architecture unifies timer-based and event-based visualizations. It is efficient because the browser takes care of everything. If nothing happens (no mouse event) and if there's no timer, nothing happens in Python and JS, so we don't waste CPU cycles for nothing.

### TODO list

* [x] find out how to deal with a context and the GLIR queue
* [x] make the backend work
* [x] make resizing work
* [x] implement mat types for uniforms
* [ ] test all examples
* [ ] implement framebuffers in the WebGL backend
* ~~put back the `ipynb_png` backend (I had to remove the  ̀vispy.js` file) (in another PR)~~

We cannot do this. It might happen to work in some examples, but in general, `update()` should just return, and the actual new draw event should be emitted in "the next iteration of the event loop". I am not sure when that would be in this situation, I am trying to figure that out :)