UNIVERSITY OF WATERLOO Software Engineering Comparison of JavaScript Graph Libraries University of Waterloo Waterloo, Ontario prepared by Yuguang Zhang Student ID: 20311196 Userid: y279zhan 2B Software Engineering January 1, 2011
1828 Blackwater Rd. London, ON N5X 4J4 January 1, 2011 Charles Stross, Director Software Engineering University of Waterloo Waterloo, ON N2L 3G1 Dear Sir, I have prepared the enclosed report Comparison of JavaScript Graph Libraries as my 2B Work Report for academic credit following my work-term. This is my third work report. I have been working on a personal project to display the university s course catalog, in a form that is easy to navigate. One of the goals of the project was a tree diagram for the prerequisites of each course. My initial assumption was that each course only had one set of prerequisites. This assumption simplified the implementation to the degree that no client-side interactivity was required. However, on careful examination of the dataset for prerequisites, it was found that many courses had multiple sets of possible prerequisites. Therefore, client-side interactivity would be beneficial and could reduce program complexity in the case where alternatives are to be shown. Following this paradigm, a prerequisite diagram would be drawn using JavaScript. The nodes of the diagram are toggled to show an alternative list of prerequisites. The purpose of this self-study report is to find and justify the library to be used for rendering the visualization of data in the project. I would like to thank Thomas Dimson for developing the L A TEX class used to typeset this report. I hereby confirm that I have received no further help other than what is mentioned above in writing this report. I also confirm that this report has not been previously submitted for academic credit at this or any other academic institution. Sincerely, Yuguang Zhang
Executive Summary This report will help web developers who are interested in visualizing graphs in JavaScript decide on a library to use. The web developer will have a clear idea of limitations and capabilities of JavaScript graph visualization libraries. Two libraries that are able to draw graph structures are JavaScript InfoVis Toolkit (JIT) and Dracula. The recommendations in this report are specific to web applications that require interactivity and are limited to a short development time. The two graph libraries are evaluated by their support for AJAX and the quality of the graph visualization. The sections of the report are ordered by importance, and each section compares JIT with Dracula. A high level overview of the processes involved in drawing a graph with each library is given. Next, AJAX support, which is essential for interactive data driven applications, is examined. Third, the graph visualization is compared. Finally, browser compatibility, the last concern due to newer browsers always having better standards support, is briefly discussed. Both JIT and Dracula are both able to satisfy basic project requirements. Dracula requires more development time to implement the same feature set as JIT. However, Dracula is easier to get started with. JIT has a low-level graph implementation that allows switching of nodes. Dracula is expedient when it comes to drawing the graph, but not when changing it. This report recommends JIT for use on data visualization projects for the web that require interactivity. This will allow fast progress during development and ensure the requirements of the application users are met. ii
Table of Contents Executive Summary................................. ii Table of Contents................................... iii 1.0 Introduction................................... 1 2.0 Background.................................... 1 3.0 Purpose...................................... 2 4.0 Scope....................................... 3 5.0 Audience..................................... 3 6.0 Outline...................................... 4 7.0 Specifying and Drawing the Graph...................... 5 7.1 JIT......................................... 5 7.2 Dracula...................................... 6 8.0 Interactivity and Dynamic Rendering.................... 7 8.1 AJAX Support.................................. 7 8.2 Data Structure for Nodes............................. 8 9.0 Visualization................................... 9 9.1 Animations.................................... 9 9.2 Graph Layout................................... 10 10.0Browser Support................................. 11 11.0Conclusions.................................... 11 iii
12.0Recommendations................................ 14 References....................................... 15 Glossary........................................ 18 iv
1.0 Introduction When developing web applications, JavaScript can help make the content more interactive. JavaScript libraries can help the developer abstract implementation details and complete the project faster. JavaScript graph visualization libraries differ in implementation and suitable application, some requiring a specific data structure for input, others have simpler methods for specifying the graph. Besides the notation for transferring data, AJAX support is worth a close examination, since it determines the interactivity of the web application. The ability to redraw nodes with AJAX is one criteria of the framework. A clean notation for relationship between the nodes of a graph is complementary. This would in turn reduce server-side processing for the graph. AJAX support is essential for reducing development time. When adding or removing nodes, transitions can make the user experience smoother. Relevant animations are particularly useful for getting the users attention. After updating the graph with AJAX, the user must be notified of the change. Animations for drawing and removing nodes are cues that can help the user understand how to interact with the graph, making the interface more intuitive. Lastly, browser support is always a consideration when developing web applications. It is important to ensure that the graph works on all browsers. Popular browsers including Internet Explorer 7 and 8, Firefox 3, Chrome, and Opera need to be checked. 2.0 Background I have been working on a personal project to gather course information from the undergrad academic calendar and display it in a user-friendly way. For the client-side part of the web application, a navigable tree of nodes is required. This is one of the primary goals of 1
the project. There are many aspects to this problem, including displaying the information, storing it, and gathering the data. How the data is displayed is completely independent from how it is gathered, because the separate functions are modularized. At the time this report is written, the only steps left required to display the information in a tree form are functions to transform data into a form which can be used by the JavaScript library and the code written using the library to display the tree. For manipulating the data, several functions were already written. They include a recursive function that returns a recursive list of course prerequisites, as well as two other functions that return the connections between nodes and the nodes separated by levels. Since this is one small component of the entire project, I decided to devote at most an entire weekend to it to build a prototype that meets all of the specifications. There are a few design constraints limiting the qualifying JavaScript library. First, the library must be capable of rendering lines and nodes. Second, the rendered graph must allow user interaction with nodes. Third, the method for drawing the graph must be standards compliant and be supported on all five major browsers. 3.0 Purpose There are several design constraints for the library to be used for visualization. First, the graph library should support an Ajax method for updating nodes. Along with dynamically adding or removing nodes of the graph, most of the intensive processing should be done by the client. Related to the amount of processing done by the server is the notation for specifying relationship between nodes. If the notation requires specific edges between all of the nodes, more computation is required than a notation that supports recursive structures. Second, the visualization is a major part of the user experience and should have relevant 2
animations. Animations for drawing and removing edges are the most applicable ones. Moreover, the nodes should by default be drawn as a tree, with each children of a node drawn at the same level of height. Preferably, the nodes have styling options so that it can be customized to fit the rest of the application. Third, browser support is an important consideration when developing any web application. The underlying technology used by the library should be forward compatible and standardized. All major browsers should be supported, with improvements or enhancements in the newer releases. 4.0 Scope This report includes qualitative and quantitative analyses of two JavaScript graph libraries, Dracula and JIT. Both are selected because they meet the constraints. Additionally, they represent two different approaches to drawing graphs. One has separation of the the graph model, layout algorithms, and rendering scheme layers. The other is has a specialized class to handle all graph operations. 5.0 Audience The audience is expected to have a basic understanding of tree graphs along with some understanding of HTML and JavaScript. In addition, a knowledge of how AJAX works is helpful. 3
6.0 Outline The different sections of this report cover the analysis of Dracula and JIT. The major sections analyze the graph specification, AJAX support, data visualization, and browser support, respectively. The final sections cover the conclusion and recommendations. 4
7.0 Specifying and Drawing the Graph In the simplest usage cases, JavaScript graph libraries take the graph specifications, rendering the nodes and edges of the graph. JIT and Dracula take different inputs for the graph, but have similar processes in rendering it. Because JIT provides many methods for manipulating the graph with a high level of abstraction, there is no need to modify the process for drawing a graph. However, there are areas that can be customized when creating nodes and requesting new nodes. On the contrary, Dracula is a much smaller library. Consequently, the rendering process needs some additions and modifications to suit the needs of the application. 7.1 JIT The JavaScript InfoVis Toolkit (JIT) has a specialized visualization class for drawing trees. Drawing a graph in a tree structure takes four steps. First, a new Space Tree instance is created. Second, a method is called to load JSON into the tree object. Third, the node positions and layout are computed. Finally, a click is simulated on the root node to draw the graph. The purpose of the click is to center the graph on the root node, as Space Tree has a feature that animates nodes that are clicked. [13] The graph is specified in JSON notation when using the JavaScript InfoVis Toolkit. In JSON notation, brackets act as containers, much like dictionaries in Python, which is used on the server side. Square brackets hold arrays. Properties and values are separated by colon. [5] Each graph node in the JSON has several properties. The id is a unique identifier for the node. The name is the text displayed for the node. Data stores optional information not used by JIT. The children property of a node contains an array of other nodes or can be empty. 5
The oncreatelabel method is called when each DOM label is created. [12] Event handlers are registered and label styles are set in this method. An HTML label element is passed. Styles are set using JavaScripts object.style.property syntax. To add more flexibility to how labels are displayed, JIT also supports SVG and Canvas labels. [3] SVG elements can be rotated so that the label text does not need to be horizontal. JIT provides an optional request method that allows nodes to be populated to a certain depth. For instance, if a node is removed and only the next level of children added, this method is called until the children are a certain depth from the root node specified. This is a method for dynamically retrieving nodes. It is asynchronous, supporting a callback function that can be registered to make the AJAX request to populate nodes. [12] 7.2 Dracula The Dracula library is divided into three layers, consisting of the graph model, layout algorithms, and rendering schemes. The graph model is an object which keeps track of nodes and edges that are added using methods in the graph class. The layout class positions nodes. The renderer class uses another JavaScript library, Raphael, to draw the graph as an SVG image. [6] This layer also supports registering events to shapes. Drawing a graph using Dracula is simple. A new graph object is created, which contains arrays for nodes, edges, and snapshots. Snapshots are saves of previous graph states. There are functions to add nodes and edges. The addnode method simply takes the name of a node as an argument and adds a node to the node array. The addedge method takes two node names and adds an edge to the array. [15] If the nodes do not exist, the nodes are created automatically when the edge is added. Each edge stores source, target, and styling information. 6
The layout algorithm takes the graph model as an argument and calculates the position of nodes. There are two layout modes available, spring and tree. Spring layout positions nodes randomly so that they are equally spaced. Tree layout positions nodes in a tree shape. The rendering scheme takes a graph as an argument and draws it using the Raphael library. Node and edge styles can be customized by passing extra arguments to the addnode method of a graph. The label for a node, by default the same as the name in the graph model, is rendered at the center of the node. 8.0 Interactivity and Dynamic Rendering One major benefit of using JavaScript to draw graphs rather than generating static images server-side is that the users can interact with the graph. Interactive client-side applications depend on AJAX. JIT has functions specifically designed for populating nodes with AJAX. On the contrary, Dracula simply lacks support for AJAX. However, Dracula is capable of more animations and allows more events to be registered than JIT. 8.1 AJAX Support JIT has a native function for requesting AJAX tree nodes, the request method. This is called when an empty node is clicked. The nodes sub-trees are requested and drawn. The request method is a high-level implementation for generating on-demand nodes. For the needs of the project, low-level details need to be controlled, making the request method unsuitable. JIT provides addsubtree and removesubtree specifically for adding or removing sub-trees from nodes. [13] Furthermore, onclick event handlers can be registered with each label. These functionalities, combined together, allow switching of nodes to show an alternative list of prerequisites. Overall, JIT has a well-rounded API to support AJAX. 7
Contrarily, Dracula has no native AJAX support and lacks methods required to execute it for the project. The method for removing nodes is not implemented. Only the rendering class uses the Raphael SVG drawing library and can remove elements from the drawing. Because the rendering class takes the graph as an argument, it is impossible to remove nodes simply by deleting them from the graph object. The separation of layers makes communication between them difficult. Changes to the graph model do not propagate to the rendering layer. Therefore, nodes cannot be added or removed dynamically with Dracula. 8.2 Data Structure for Nodes The data structure for specifying the tree is directly related to the amount of processing required for the back-end. Since a recursive query is used to generate prerequisites, it is more convenient to use a notation for specifying nodes that supports recursive structures. JIT requires the back-end to generate a JSON data structure to represent the tree. Since there is a children property in each node object, fully recursive structures are supported. The child property is of type Array and contains a nodes children. [14] Besides during the initial load, JSON is used throughout the library to specify tree or graph structures, including adding and removing nodes. With Dracula, the back-end has to provide two sets of data for the graph. The edges between nodes must be specified to draw lines between them. This is in the format of node pairs passed as arguments to a function. Specifying nodes are optional for drawing the graph, since they are added automatically. However, in order to avoid overlapping of edges, the nodes for each level must be provided in a certain order, from left to right, top to bottom. The nodes on each level are specified before moving on to the next. This is done by simply passing the nodes name in a function call. Certainly, the lack of JSON structure has a side effect. Edges in the graph model are used to keep track of relationships between nodes. 8
To find the children of a node, all edges are searched. Each edge has a source and target property. The source s id must match the node s id to find its children. In summary, there are many drawbacks compared to JIT when adding and removing nodes because the default graph structure is not recursive. 9.0 Visualization Visualizing the information contained in data is critical to communicating it. There is a huge difference in user experience between navigating through several pages to obtain a list of prerequisites and getting a glance of it as a tree structured graph. In the first case, the users flow of thought is interrupted as each page loads, and the user must keep track sequence of prerequisites. In the second case, an intuitive graph structure along with the animations allows the user to immediately find the information they are looking for. In order to realize the user interface for the second case, animations should make interacting with the graph a smooth experience. Nodes should be styled in a way that encourages user interaction. 9.1 Animations Although JIT comes with fewer animations compared to the Raphael based library Dracula, it has all of the most essentials ones. JIT has animations for adding and removing nodes. In addition, tooltips can be added for mouse hovers. The animation for adding a node simply traces the branch of the tree drawn as a line and fades in the node. Styled tooltips can be added for mouse hovers. These animations are particularly relevant for visualizing prerequisites as a tree structure. In Dracula, nodes are drawn as shapes, which can be colored and labeled by setting attributes of the SVG element.[8] These can be set directly through an attr method. Many of 9
the styling options and animations in the SVG specification are supported in Dracula through an optional Raphael parameter that can be passed when making a node. [16] The optional parameter, a lambda function, uses Raphael to set styles and animations. [15] It takes the SVG element Raphael draws on and the node as arguments and returns a Raphael set of objects. As a result, Dracula has all the SVG drawing capabilities of Raphael. Although the Dracula library could be customized to animate the drawing of a tree the same way as JIT, Dracula by default does not come with relevant animations. Conversely, it comes with a few animations to support dragging. When a node is clicked, the node fades in color, which is not particularly useful for the current application. 9.2 Graph Layout JIT has all the basic features for drawing tree structured graphs. JIT lays out nodes so that edges do not overlap, except for the case where the children refer to parents as children. However, this case does not occur when simply displaying prerequisites. At any rate, JIT lays out the nodes in an aesthetically pleasing way. [4] Equally important, nodes can be styled with several properties. [11] The style options include the nodes shape, color, opacity, height, and width. Dracula has support for tree mode layout [10] in which nodes are laid out from top to bottom, level by level. All of a nodes children are on the same level, however, Dracula needs nodes to be arranged level by level to avoid edges crossing. There is no attempt to prevent overlapping of edges in the layout algorithm. Fortunately, there were Python functions written to process nodes and separate them into different levels which are suitable for this task. Nodes can be styled using an object passed when creating them without directly using Raphael. [15] This is mostly a convenience and supports gradients, stroke styles, font options, rotation, and position options. 10
10.0 Browser Support Both libraries have support for all major browsers. JIT uses the HTML5 Canvas element, and Dracula uses SVG. For versions of IE that doesnt support Canvas, the ExCanvas library bridges the gap. Similarly, the Raphael based library Dracula uses VML in place of SVG for IE. [17] The next release of IE is expected to be on par with modern browsers, as IE9 supports both Canvas and SVG. [18] Although the underlying implementation behind Dracula supports IE, it only works in IE with a small tweak. Specifically, the foreach loop needs to be changed to a for loop. [9] This is because IEs JavaScript implementation does not have foreach. JIT has higher performance due to everything being rendered as a pixel compared to Raphael, which updates the XML document, adding complexity. On a surprising note, JIT is noticeably slower in browsers that dont have modern JavaScript engines, since all animations and drawings are calculated using JavaScript. However, the JavaScript engine is expected to improve in IE9[19], which will make the animations smoother. 11.0 Conclusions JIT has a specialized class for tree graphs that makes adding and removing nodes simple. Creating a tree graph only requires initializing the class, loading the graph specification, and calling methods to compute the layout. JIT comes with support for JSON, which is used to load the initial graph structure. JITs node representation is particularly suitable for recursive structures, as each node can have children. Each node has an extra data property, which can be customized to store the iteration number through prerequisites. In addition, JIT has a method for repeatedly requesting nodes until the tree has a certain depth. This feature can be used for loading the tree initially or populating the tree after nodes are removed. 11
The Dracula graph library has three layers for the graph model, layout algorithms, and rendering schemes. This separation of layers makes it easy to add nodes to the graph model or style nodes and edges on the drawing. However, this separation of layers also increases the complexity of implementing a method for removing nodes from the drawing. Nodes cannot be removed simply by changing the graph model. When creating the graph, Dracula allows the graph to be specified by the connections between nodes. This makes the learning curve for the library short, as there is a minimal amount of structure in the graph specification. On the other hand, it does come with drawbacks for manipulating nodes with AJAX. JIT has better AJAX support compared to Dracula. Dracula is hardly intended to be used with AJAX for changing the graph, as it does not support removing nodes. Furthermore, Dracula requires additional processing of the tree as input before it can be drawn. On the other hand, JIT has methods for adding and removing nodes and JSON for tree structure. The JSON data structure is recursive, allowing nodes to be nested. When it comes to visualizing recursive structures, JIT has more relevant animations and offers more features. The animations are geared towards displaying trees, with contraction and expansion animations for adding and removing nodes. Not only do the layout algorithms avoid overlapping of edges in the graph by default, but also several node appearance options can be styled. Dracula has a plethora of available animations and styling options for visualizing general graph structures. These are not built into Dracula or specific for drawing tree structures. Nevertheless, Dracula can be customized to include animations for drawing trees due to its support of SVG. Although the layout algorithm does not prevent overlapping of edges, a pre-written python function can order nodes to be drawn in a sequence so that they do not overlap. When styling nodes, Dracula makes it convenient to set a large number of options. Dracula and JIT use different web technologies for rendering graphics. Dracula has a 12
slight incompatibility with IE that can be fixed. IE9 is expected to natively support Canvas and SVG, the underlying technologies behind JIT and Dracula. In terms of compatibility with older versions of IE, the only issue with JIT is that there is a noticeable performance penalty. 13
12.0 Recommendations Because the Dracula graph library lacks essential methods required for the project, it should be avoided unless the project timeline can be extended. Even if the timeline is extended, the three layer structure of the library may result in unexpected problems during development. Due to the short development time allocated for this part of the project, it is unsuitable to use Dracula even if more animations and styles are available. They are simply too general to use for drawing tree graphs. It is recommended to use JITs specialized class for drawing trees, as this will fulfill the basic project requirements and shorten development time. In order to avoid patching future releases of Dracula for IE support, it is suggested to use JIT. Both libraries use standardized web technologies, while using JIT can save a small amount of time due to out of box support for all major browsers. 14
References [1] F. Potencier, Practical symfony, http://www.symfony-project.org/jobeet/1_4/ Doctrine/en/ (current April 2010). [2] F. Potencier, Chapter 5 - Configuring Symfony, in The Definitive Guide to symfony, http://www.symfony-project.org/book/1_0/05-configuring-symfony (current April 2010). [3] N. G. Belmonte, HTML, SVG or Canvas Labels?, http://blog.thejit.org/2009/ 08/30/html-svg-or-canvas-labels/ (current December 2010). [4] N. G. Belmonte, Drawing Trees, http://blog.thejit.org/2009/08/05/ drawing-trees/ (current December 2010). [5] P. Hunlock, Mastering JSON ( JavaScript Object Notation ), in The Javascript Reference Series, http://www.hunlock.com/blogs/mastering_json_(_javascript_ Object_Notation_) (current December 2010). [6] D. Almaer, New Javascript/Canvas Graph library, http://ajaxian.com/archives/ new-javascriptcanvas-graph-library (current December 2010). [7] M. Sucan, SVG or Canvas? Choosing between the two, http://dev. opera.com/articles/view/svg-or-canvas-choosing-between-the-two/ #comparison-of-svg-and-canvas (current December 2010). [8] D. Baranovski, RaphalJavaScript Library Documentation, http://raphaeljs.com/ reference.html#attr (current December 2010). [9] J. Philipp, Dracula Graph Library, http://www.graphdracula.net/ (current December 2010). 15
[10] J. Philipp, Short update: new code and tree mode, http://www.graphdracula.net/ 2010/11/09/short-update-new-code-and-tree-mode/ (current December 2010). [11] N. G. Belmonte, Options.Node.js, in JavaScript InfoVis Toolkit API Documentation, http://thejit.org/static/v20/docs/files/options/options-node-js.html (current December 2010). [12] N. G. Belmonte, Options.Controller.js, in JavaScript InfoVis Toolkit API Documentation, http://thejit.org/static/v20/docs/files/options/ Options-Controller-js.html (current December 2010). [13] N. G. Belmonte, Spacetree.js, in JavaScript InfoVis Toolkit API Documentation, http://thejit.org/static/v20/docs/files/visualizations/spacetree-js.html (current December 2010). [14] N. G. Belmonte, loadjson, in JavaScript InfoVis Toolkit API Documentation, http: //thejit.org/static/v20/docs/files/loader/loader-js.html#loader.loadjson (current December 2010). [15] J. Philipp, Documentation, http://www.graphdracula.net/documentation/ (current December 2010). [16] E. Dahlstrm et al., Scalable Vector Graphics (SVG) 1.1 (Second Edition), http: //www.w3.org/tr/svg/ (current December 2010). [17] D. Baranovski, RaphalJavaScript Library, http://raphaeljs.com/ (current December 2010). [18] R. Bango, An Introduction to the HTML 5 Canvas Element, http://msdn. microsoft.com/en-us/scriptjunkie/ff961912.aspx (current December 2010). [19] S. Niyogi, The New JavaScript Engine in Internet Explorer 9, http://blogs.msdn.com/b/ie/archive/2010/03/18/ 16
the-new-javascript-engine-in-internet-explorer-9.aspx (current December 2010). 17
Glossary AJAX A group of techniques for creating interactive web applications, in which applications can retrieve data from the server asynchronously in the background without interfering with the display and behavior of the existing page. HTML Hypertext Markup Language: a set of tags and rules (conforming to SGML) for using them in developing hypertext documents. CSS Cascading Style Sheets are declarations that describe how a document should be presented on the Web. Python A simple, high-level interpreted language invented by Guido van Rossum in 1991. JavaScript A scripting programming language most commonly used to add interactive features to webpages. 18