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)~~

Because the other backends support it. It is shorter and easier than using a timer. This is what process_events is for. I suppose you could argue that it is a rare feature, and we can live with it not being available here. But then we should probably raise an error here rather than pass.