Lucid Digital Media
Blog Categories
Flow charting application
Recently we were commissioned to work on an unusual project. The brief was to work on a browser based flow charting application, using only in browser technologies and no plug-ins like Adobe's Flash or Microsoft's Silverlight. As if that wasn't challenge enough, the resulting application had to allow a number of users to collaborate simultaneously on the same documents.
Drawing in the browser without Flash
The basic drawing requirement for the application was fairly simple, its simply had to draw filled circles (with a drop shadow effect) and be able to draw single or double headed arrows between the circles, maintaining the connection between the shapes when they are moved around. The user had to have the ability to add text to the circles and the arrows by double clicking on them and typing on to the shape or arrow.
Doing this sort of thing, whilst not simple, would be far easier using Flash or Silverlight, but given had to do everything using using native browser features we needed something different. Recently we'd been researching a javascript library called Raphael as a possible Flash replacement in certain circumstances. Raphael differs from typical javascript libraries in that it deals almost exclusively with drawing vector images, something that jQuery or Prototype wont do.
Using Raphael we were able to draw proper vector based circles and arrows. Using some clever script we were able to calculate how to draw nicely curved arrows between shapes regardless of their orientation to each other. Raphael hooks in to the browser DOM model so we can add onclick and other events to the shapes and this allowed us to implement relatively simple drag and drop functionality. Raphael also supports vector text, which mean't we could even implement the arrow and circle text within the Raphael based system. To get text into the document we had a simple text area form input which we could move and resize to the relative position of each shape, when it wasn't needed it could be hidden using simple CSS and javascript.
So that was the basics of the drawing system, and once we had all the pieces it came together very quickly. It took about 2.5 days to meet the drawing requirements of the brief and what we had worked very well with no use of Flash anywhere.
Communicating with the Server and other users
The next challenge would be the multi-user collaboration aspect of the brief. There would have been two obvious options here:
- Use a hidden flash movie to send updates to some customer server software using an XML socket, the server software would send distribute updates to all the other connected browsers instantly.
- Use AJAX to periodically poll the server for changes, when a change is made, the browser would send an AJAX update to the server which would then update all the connected browsers the next time their polled the server to check for updates.
Because our brief said we were not allowed to use Flash, our two possible options became one, the AJAX approach.
The process was relatively simple but took a lot of tuning to get it to work in a natural way. Every time an update was made to a chart, the browser would send a light weight update to the server, this was basically a pipe separate string containing the ID of the item that had been modified, and all information about its updated state. The server would store a transcript of these micro updates, with each update being given an unique update ID. Each browser would keep track of the current update ID they were working with and would send this to the server on each update request, in this way the server would only send updates which the browser didn't already have.
The connected browsers would poll the server every 1 second with a light weight request for any updates that had been made to the currently open document (sending their current update ID). In response the server would send all the micro-updates the browser didn't already have. The browser would then run through the updates in order, changing elements it already knew about and adding new elements to the canvas if required. In this way the state of the canvas on each connected browser should always be consistent with the state of the chart as logged at the server.
The nice thing about this system was that because every change to the chart was logged and every update automatically played back until the browser was up to date, you could refresh the page (or even close the browser), then return to the chart and see the chart exactly as you had left it (or with the additions other people might have made to it since). So as a side effect, we got a very robust auto save function.
We also added a nice 'save point' feature so you could take a 'snapshot' of a chart at any point and then return to that snapshot if you made changes you didn't want to keep, this gave the user the best of both worlds!