2012-05-21 20:32:26 +00:00
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>mxGraph User Manual - JavaScript Client</title>
|
2012-09-28 07:03:08 +00:00
|
|
|
<link rel="stylesheet" href="css/manual-styles.css">
|
|
|
|
<link rel="stylesheet" href="css/manual-colors.css">
|
2012-05-21 20:32:26 +00:00
|
|
|
<script type="text/javascript" src="js/toc.js"></script>
|
|
|
|
</head>
|
|
|
|
<body onload="maketoc(document.getElementById('toc'));">
|
|
|
|
<h1>mxGraph User Manual – JavaScript Client</h1>
|
|
|
|
<br/>
|
|
|
|
<br/>
|
2015-12-11 09:22:19 +00:00
|
|
|
<p>mxGraph Version 3.4.1.0 – 11. December 2015</p>
|
2013-06-28 19:07:06 +00:00
|
|
|
<p>Copyright (c) JGraph Ltd 2006-2013</p>
|
2012-05-21 20:32:26 +00:00
|
|
|
<br/>
|
|
|
|
<p>All rights reserved. No part of this publication may be
|
|
|
|
reproduced, stored in a retrieval system, or transmitted in any form or
|
|
|
|
by any means, electronic, mechanical, photocopying, recording or
|
|
|
|
otherwise, without the prior written permission of the author.</p>
|
|
|
|
<p>The programs in this book have been included for their
|
|
|
|
instructional value. They have been tested with care but are not
|
|
|
|
guaranteed for any particular purpose. The publisher does not offer any
|
|
|
|
warranties or representations nor does it accept any liabilities with
|
|
|
|
respect to the programs.</p>
|
|
|
|
|
|
|
|
<p>Possession, use, or copying of the software described in this
|
|
|
|
publication is authorized only pursuant to a valid written license from
|
|
|
|
JGraph Ltd.</p>
|
|
|
|
|
|
|
|
<p>Neither JGraph Ltd. nor its employees are responsible for any
|
|
|
|
errors that may appear in this publication. The information in this
|
|
|
|
publication is subject to change without notice.</p>
|
|
|
|
<p>Java and all Java-based marks are trademarks or registered
|
|
|
|
trademarks of Sun Microsystems, Inc. in the U.S. and other countries.</p>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
<h1>Table Of Contents</h1>
|
|
|
|
<div id="toc"></div>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
<h1><a name="Introduction"></a>Introduction</h1>
|
2013-06-28 19:07:06 +00:00
|
|
|
<h2><a name="mxGraph_Products"></a>Product Introduction</h2>
|
2012-05-21 20:32:26 +00:00
|
|
|
|
2013-06-28 19:07:06 +00:00
|
|
|
<p>mxGraph is a JavaScript component that provides features aimed at applications that display
|
2012-05-21 20:32:26 +00:00
|
|
|
interactive <a href="http://en.wikipedia.org/wiki/Diagram">diagrams</a>
|
|
|
|
and graphs. Note by graphs we mean <a
|
|
|
|
href="http://en.wikipedia.org/wiki/Graph_(mathematics)">mathematical
|
|
|
|
graphs</a>, not necessarily <a href="http://en.wikipedia.org/wiki/Charts">charts</a>
|
|
|
|
(although some charts are graphs). See later section “What is a
|
|
|
|
Graph?” for more details.</p>
|
|
|
|
|
|
|
|
<p>Being a developer library, mxGraph is not designed specifically
|
|
|
|
to provide a ready to use application, although many of the examples are
|
|
|
|
close to being usable applications. mxGraph provides all the commonly
|
|
|
|
required functionality to draw, interact with and associate a context
|
2013-06-28 19:07:06 +00:00
|
|
|
with a diagram. mxGraph comes with a number of examples that help explain how a
|
|
|
|
basic application is put together and showcases
|
2012-05-21 20:32:26 +00:00
|
|
|
individual features of the library.</p>
|
|
|
|
|
|
|
|
<p>Developers integrating the library in their application should
|
2013-06-28 19:07:06 +00:00
|
|
|
read the section
|
2012-05-21 20:32:26 +00:00
|
|
|
“Pre-requisites” below. Given that mxGraph is a component
|
2013-06-28 19:07:06 +00:00
|
|
|
part of your application, you must understand how JavaScript web
|
|
|
|
applications are constructed at an architectural level, and how to program
|
|
|
|
both in JavaScript, as well as any server-side languages used.</p>
|
2012-05-21 20:32:26 +00:00
|
|
|
|
2013-06-28 19:07:06 +00:00
|
|
|
<p>mxGraph mainly comprises one JavaScript
|
2012-05-21 20:32:26 +00:00
|
|
|
file that contains all of the mxGraph functionality. This is loaded into
|
|
|
|
a HTML web page in a JavaScript section and executes in an HTML
|
|
|
|
container in the browser. This is an incredibly simple architecture that
|
|
|
|
only requires a web server capable of serving html pages and a
|
|
|
|
JavaScript enabled web browser.</p>
|
|
|
|
|
|
|
|
<p>The key advantages of this technology are:</p>
|
|
|
|
<ul>
|
|
|
|
<li>That no third-party plug-ins are required. This removes
|
|
|
|
plug-in vendor dependence.</li>
|
|
|
|
<li>The technologies involved are open and there are many open
|
2013-06-28 19:07:06 +00:00
|
|
|
implementations, no one vendor can remove a product or technology that
|
2012-05-21 20:32:26 +00:00
|
|
|
leaves your application unworkable in practise.</li>
|
|
|
|
<li>Standardized technologies, meaning your application is
|
|
|
|
deployable to the maximum number of browser users without need for
|
|
|
|
additional configuration or installation at the client computer. Large
|
|
|
|
corporate environments often dislike allowing individuals to install
|
|
|
|
browser plug-ins and do not like to change the standard build rolled
|
|
|
|
out to all machines.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_architecture.png" name="mxgraph_architecture" />
|
|
|
|
<br/>
|
|
|
|
<em>The mxGraph components and their relationships</em></p>
|
|
|
|
|
|
|
|
<h2><a name="mxgraph_applications"></a>What Applications can
|
|
|
|
mxGraph be used for?</h2>
|
|
|
|
|
|
|
|
<p>Example applications for a graph visualization library include:
|
|
|
|
process diagrams, workflow and BPM visualization, flowcharts, traffic or
|
|
|
|
water flow, database and WWW visualization, networks and
|
|
|
|
telecommunications displays, mapping applications and GIS, UML diagrams,
|
|
|
|
electronic circuits, VLSI, CAD, financial and social networks, data
|
|
|
|
mining, biochemistry, ecological cycles, entity and cause-effect
|
|
|
|
relationships and organisational charts.</p>
|
|
|
|
|
|
|
|
<h2><a name="mxgraph_deployment"></a>How is mxGraph deployed?</h2>
|
|
|
|
|
|
|
|
<p>In the typical thin-client environment, mxGraph is split into the
|
|
|
|
client-side JavaScript library and a server-side library in one of the
|
|
|
|
two supported languages, .NET and Java. The JavaScript library is
|
|
|
|
contained as part of a larger web application that is delivered to the
|
|
|
|
browser using a standard web server. All the browser needs is the
|
|
|
|
ability to run JavaScript to be enabled.</p>
|
|
|
|
|
|
|
|
<p>In the third part of this manual, you will see an example of an
|
|
|
|
html page that embeds the mxGraph library, as well as a simple
|
|
|
|
application to invoke the library's functionality.</p>
|
|
|
|
|
|
|
|
<h2><a name="mxgraph_technologies"></a>mxGraph Technologies</h2>
|
|
|
|
|
|
|
|
<p>mxGraph uses JavaScript for the client-side functionality on the
|
|
|
|
browser. The JavaScript code in turn uses the underlying vector graphics
|
|
|
|
language on the active browser to render the displayed diagram, SVG for
|
|
|
|
the more standards compliant browsers and VML in the case of Microsoft
|
|
|
|
Internet Explorer. mxGraph also includes the feature to render entirely
|
|
|
|
using html, this limits the range of functionality available, but is
|
|
|
|
suitable for more simple diagrams.</p>
|
|
|
|
|
|
|
|
<p>As a developer you are not exposed to browser specific features.
|
|
|
|
As mentioned, the vector graphics language varies by browser, so mxGraph
|
|
|
|
abstracts their features into a common class. Similarly, for event
|
|
|
|
handling and DOMs. Browsers differ in their implementation of these two
|
|
|
|
major browser functionalities, mxGraph exposes a constant API over all
|
|
|
|
browsers and adapts to the inconsistencies behind the scenes.</p>
|
|
|
|
|
|
|
|
<h2><a name="mxgraph_licensing"></a>mxGraph Licensing</h2>
|
|
|
|
|
2013-06-28 19:07:06 +00:00
|
|
|
<p>The JavaScript client of mxGraph is licensed under a
|
|
|
|
<a href="http://www.jgraph.com/mxlicense.html"> standard
|
|
|
|
commercial license</a> For detailed licensing questions you are always advised to
|
|
|
|
consult a legal professional.
|
2012-05-21 20:32:26 +00:00
|
|
|
|
|
|
|
<h2><a name="what_graph"></a>What is a Graph?</h2>
|
|
|
|
|
|
|
|
<p>Graph visualization is based on the mathematical theory of
|
|
|
|
networks, graph theory. If you're seeking JavaScript bar <em>charts</em>,
|
|
|
|
pie <em>charts</em>, Gantt <em>charts</em>, have a look at the <a
|
|
|
|
href="http://code.google.com/apis/chart/">Google Charts</a> project
|
|
|
|
instead, or similar</p>
|
|
|
|
<p>A graph consists of vertices, also called nodes, and of edges
|
|
|
|
(the connecting lines between the nodes). Exactly how a graph appears
|
|
|
|
visually is not defined in graph theory. The term <em>cell</em> will be
|
|
|
|
used throughout this manual to describe an element of a graph, either
|
|
|
|
edges, vertices or groups.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_simple_graph.png" /><br/>
|
|
|
|
<em>A simple Graph</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>There are additional definitions in graph theory that provide
|
|
|
|
useful background when dealing with graphs, they are listed in the
|
|
|
|
Appendices if of interest to you.</p>
|
|
|
|
|
|
|
|
<h3><a name="graph_visualization"></a>Graph Visualization</h3>
|
|
|
|
|
|
|
|
<p>Visualization is the process of creating a useful visual
|
|
|
|
representation of a graph. The scope of visualization functionality is
|
|
|
|
one of mxGraphs' main strength. mxGraph supports a wide range of
|
|
|
|
features to enable the display of cells to only be limited by the skill
|
|
|
|
of the developer and the platform functionality available. Vertices may
|
|
|
|
be shapes, images, vector drawing, animations, virtually any graphical
|
|
|
|
operations available in browsers. You can also use HTML mark-up in both
|
|
|
|
vertices and edges.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_graph_vis.png"><br/>
|
|
|
|
<em>Graph Visualization of a transport system. (c) Tourizm Maps
|
|
|
|
2003, http://www.world-maps.co.uk</em></p>
|
|
|
|
<br/>
|
|
|
|
<h3><a name="graph_interaction"></a>Graph Interaction</h3>
|
|
|
|
|
|
|
|
<p>Interaction is the way in which an application using mxGraph can
|
|
|
|
alter the graph model through the web application GUI. mxGraph supports
|
|
|
|
dragging and cloning cells, re-sizing and re-shaping, connecting and
|
|
|
|
disconnecting, drag and dropping from external sources, editing cell
|
|
|
|
labels in-place and more. One of the key benefits of mxGraph is the
|
|
|
|
flexibility of how interaction can be programmed.</p>
|
|
|
|
|
|
|
|
<p>Many complex graphical web applications rely on a round-trip to
|
|
|
|
the server in order to form the display, not only the base display but
|
|
|
|
also the interaction events. Although this is often given the title of
|
|
|
|
AJAX functionality, such server reliance is not appropriate for
|
|
|
|
interaction events. Visual feedback taking longer than about 0.2 seconds
|
|
|
|
in an application generally seriously impacts the usability. By placing
|
|
|
|
all of the interaction on the client, mxGraph provides the true feel of
|
|
|
|
a application, rather than seeming like a dumb remote terminal. It also
|
|
|
|
allows the possibility of off-line use.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_graph_interaction.png" /><br/>
|
|
|
|
<em>Selection shading while selecting an area through mouse drag</em></p>
|
|
|
|
<br/>
|
|
|
|
<h3><a name="graph_layouts"></a>Graph Layouts</h3>
|
|
|
|
|
|
|
|
<p>Graph cells can be drawn anywhere in a simple application,
|
|
|
|
including on top of one another. Certain applications need to present
|
|
|
|
their information in a generally ordered, or specifically ordered
|
|
|
|
structure. This might involve ensuring cells do not overlap and stay at
|
|
|
|
least a certain distance from one another, or that cells appear in
|
|
|
|
specific positions relative to other cells, usually the cells they are
|
|
|
|
connected to by edges. This activity, called the layout application, can
|
|
|
|
be used in a number of ways to assist users in setting out their graph.
|
|
|
|
For non-editable graphs, layout application is the process of applying a
|
|
|
|
layout algorithm to the cells. For interactive graphs, meaning those
|
|
|
|
that can be edited through the UI, layout application might involve only
|
|
|
|
allowing users to make changes to certain cells in certain positions, to
|
|
|
|
re-apply the layout algorithm after each change to the graph, or to
|
|
|
|
apply the layout when editing is complete.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_graph_layout.png" /><br/>
|
|
|
|
<em>Layout of a workflow using a horizontal hierarchical layout</em></p>
|
|
|
|
|
|
|
|
<p>mxGraph supports a range of tree, force-directed and hierarchical
|
|
|
|
layouts which will fit most layout needs. See the later section on using
|
|
|
|
the layouts for more information.</p>
|
|
|
|
|
|
|
|
<p>In a client-server architecture there are two options for how
|
|
|
|
layouts can be run. The Javascript versions provide the ability to run
|
|
|
|
the layouting entirely on the client, while the same layout
|
|
|
|
implementation in Java on the server-side enables the option to offload
|
|
|
|
some processing to the server, if required.</p>
|
|
|
|
|
|
|
|
<h3><a name="graph_analysis"></a>Graph Analysis</h3>
|
|
|
|
|
|
|
|
<p>Analysis of graphs involves the application of algorithms
|
|
|
|
determining certain details about the graph structure, for example,
|
|
|
|
determining all routes or the shortest path between two cells. There are
|
|
|
|
more complex graph analysis algorithms, these being often applied in
|
|
|
|
domain specific tasks. Techniques such as clustering, decomposition, and
|
|
|
|
optimization tend to be targeted at certain fields of science and have
|
|
|
|
not been implemented in the core mxGraph packages at the current time of
|
|
|
|
writing.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_graph_analysis.jpg"
|
|
|
|
name="shortest_path_analyis" /><br/>
|
|
|
|
<em>Shortest Path Analysis</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<h2><a name="about_manual"></a>About this Manual</h2>
|
|
|
|
|
|
|
|
<h3><a name="pre_requisites"></a>Pre-requisites for mxGraph</h3>
|
|
|
|
|
|
|
|
<p>To benefit fully from this manual you will need to have a
|
|
|
|
reasonable understanding of web applications and of the server
|
|
|
|
technology you wish to deploy using. Deployment examples are available
|
|
|
|
for each of the server technologies supported, some familiarity with
|
|
|
|
that server technology is obviously required.</p>
|
|
|
|
|
|
|
|
<p>Basic XML knowledge is useful for changing the editor
|
|
|
|
configuration files that describe the visual and behavioural aspects of
|
|
|
|
the editor. You will need to understand and implement Javascript coding
|
|
|
|
and be familiar with object orientated programming principles and modern
|
|
|
|
software design.</p>
|
|
|
|
|
|
|
|
<p>You do not need knowledge of the underlying vector graphics
|
|
|
|
language that the browser uses, such as SVG, VML or HTML canvas. mxGraph
|
|
|
|
abstracts the description of the visual component into one API.</p>
|
|
|
|
|
|
|
|
<h1><a name="Getting_Started"></a>Getting Started</h1>
|
|
|
|
|
2013-06-28 19:07:06 +00:00
|
|
|
<h2><a name="mxgraph_site"></a>The mxGraph Package</h2>
|
2012-05-21 20:32:26 +00:00
|
|
|
|
|
|
|
<h3><a name="obtaining_mxgraph"></a>Obtaining mxGraph</h3>
|
|
|
|
|
|
|
|
<p>To evaluate mxGraph:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>Navigate to the <a
|
|
|
|
href="http://www.jgraph.com/mxdownload.html">evaluation download
|
2013-06-28 19:07:06 +00:00
|
|
|
request page</a>.</li>
|
|
|
|
<li>Please note that we require a commercial or organizational email
|
|
|
|
address to process your request. We're not able to sell mxGraph to
|
|
|
|
individuals.</li>
|
|
|
|
<li>When you receive the download details, unzip to your preferred
|
2012-05-21 20:32:26 +00:00
|
|
|
location.</li>
|
|
|
|
<li>Within the package under javascript/examples you will find a
|
|
|
|
number of html files that demonstrate how to invoke the library within
|
|
|
|
a web page.</li>
|
|
|
|
<li>To create your own example, copy the basic structure of the
|
|
|
|
examples and add your extensions/changes to the onload invoked
|
|
|
|
JavaScript main function.</li>
|
|
|
|
<li>The evaluation copy is valid for 90 days after download. If
|
|
|
|
you wish to continue evaluation please use the <a
|
|
|
|
href="http://jgraph.com/contact.html">contact form</a>.</li>
|
|
|
|
<li>For commercial evaluations looking for commercial grade
|
|
|
|
evaluation support, again, please use the <a
|
|
|
|
href="http://jgraph.com/contact.html">contact form</a>.</li>
|
|
|
|
</ul>
|
|
|
|
|
2013-06-28 19:07:06 +00:00
|
|
|
<p>There is no functional API difference between the evaluation and full
|
2012-05-21 20:32:26 +00:00
|
|
|
version of mxGraph.</p>
|
|
|
|
|
|
|
|
<h3><a name="Installing_the_JGraph_Suite"></a>Installing mxGraph</h3>
|
|
|
|
|
|
|
|
<p>Both the evaluation and full versions of mxGraph are delivered as
|
|
|
|
zip files. Unzip the package to your preferred location, a folder named
|
|
|
|
mxGraph will be created there, this folder is the root folder of the
|
|
|
|
mxGraph installation.</p>
|
|
|
|
|
|
|
|
<h3><a name="project_structure"></a>Project structure and build
|
|
|
|
options</h3>
|
|
|
|
|
|
|
|
<p>Once unzipped you will be presented with a number of files and
|
|
|
|
directories in the installation root.</p>
|
|
|
|
|
|
|
|
<TABLE WIDTH=642 BORDER=1 BORDERCOLOR="#000000" CELLPADDING=4
|
|
|
|
CELLSPACING=0>
|
|
|
|
<COL WIDTH=165>
|
|
|
|
<COL WIDTH=459>
|
|
|
|
<THEAD>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>/doc</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>Documentation root, includes this user manual</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
</THEAD>
|
|
|
|
<TBODY>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>/dotnet</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>.NET server-side classes</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>/java</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>Java server-side classes</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>/javascript</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>JavaScript client functionality.</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>/javascript/examples</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>HTML examples demonstrating the use of mxGraph</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>ChangeLog</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>Details of the changes between releases</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>index.html</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>Basic introduction to the library</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
<TR VALIGN=TOP>
|
|
|
|
<TD WIDTH=165>
|
|
|
|
<p>license.txt</p>
|
|
|
|
</TD>
|
|
|
|
<TD WIDTH=459>
|
|
|
|
<p>The licensing terms under which you must use the library</p>
|
|
|
|
</TD>
|
|
|
|
</TR>
|
|
|
|
</TBODY>
|
|
|
|
</TABLE>
|
|
|
|
|
|
|
|
<p><em>Table: Project Directory Structure</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<h2><a name="web_applications"></a>JavaScript and Web Applications</h2>
|
|
|
|
|
|
|
|
<p>Web applications, specifically the use of JavaScript to attempt
|
|
|
|
to emulate desktop application-like behaviour in web browsers, is still
|
|
|
|
a relatively new field of software engineering. There are three main
|
|
|
|
issues with JavaScript that are perceived to be a barrier to producing
|
|
|
|
high quality applications, performance, lack of native functionality
|
|
|
|
available in desktop applications and inconsistent APIs between
|
|
|
|
browsers.</p>
|
|
|
|
|
|
|
|
<p>There has been considerable effort toward developing framework
|
|
|
|
libraries to solve two of the problems, the functionality and API
|
|
|
|
issues. The requirements of many of these libraries is driven by both
|
|
|
|
improving web site design and usability, as well as to assist production
|
|
|
|
of what we generally refer to as application features (menus, windows,
|
|
|
|
dialogs, persistence, event handling, etc). They also provide certain
|
|
|
|
base functionalities missing in JavaScript that desktop application
|
|
|
|
developers take for granted, such as basic maths and collections
|
|
|
|
functionality.</p>
|
|
|
|
|
|
|
|
<p>Many of these JavaScript frameworks have IDE support for
|
|
|
|
development nowadays and all of the major browsers now contain
|
|
|
|
JavaScript debuggers, either natively or as a plug-in. There is no
|
|
|
|
compilation phase with JavaScript (it is an interpreted language) so
|
|
|
|
basic typographical errors are often only caught at runtime, unless you
|
|
|
|
obtain a syntax checking tool in your IDE. So although there is not one
|
|
|
|
complete package for your JavaScript development needs, there are a
|
|
|
|
number of vendors providing the individual components you need to
|
|
|
|
produce JavaScript applications effectively.</p>
|
|
|
|
|
|
|
|
<h3><a name="ajax"></a>AJAX</h3>
|
|
|
|
|
|
|
|
<p><a href="http://en.wikipedia.org/wiki/AJAX">AJAX</a> is a very
|
|
|
|
fashionable term applied freely to make JavaScript applications sound
|
|
|
|
more modern. The idea of AJAX was originally to enable communication
|
|
|
|
with a server without leaving the client browser hanging in a loop
|
|
|
|
waiting for the response. Strictly speaking, the basic functioning of
|
|
|
|
mxGraph involves no AJAX. All of the interaction and model changes are
|
|
|
|
applied on the client in JavaScript.</p>
|
|
|
|
|
|
|
|
<p>Alternative approaches to display interaction diagrams have been
|
|
|
|
taken that use the AJAX approach, but be weary of the AJAX term to suggest
|
|
|
|
that the solution is technological more advanced. Going back to the
|
|
|
|
server for interaction changes, in particular, cause serious delays in
|
|
|
|
updating the UI, often making the application unusable.</p>
|
|
|
|
|
|
|
|
<h3><a name="js_frameworks"></a>Third-Party JavaScript Frameworks</h3>
|
|
|
|
|
|
|
|
<h4><a name="GWT"></a>Google Web Toolkit</h4>
|
|
|
|
|
|
|
|
<p>Given the apparent complexity from a desktop developer's point of
|
|
|
|
view, a common approach is to use the <a
|
|
|
|
href="http://code.google.com/webtoolkit/">Google Web Toolkit (GWT)</a>.
|
|
|
|
GWT provides many commonly required web application features by
|
|
|
|
translating Java into JavaScript. This JavaScript can be deployed just
|
|
|
|
as natively written JavaScript is. GWT also provides the option to
|
|
|
|
obfuscate the resulting JavaScript. (See later section on obfuscation in
|
|
|
|
this chapter).</p>
|
|
|
|
|
|
|
|
<p>The key advantages of GWT are:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>Reuses Java developer knowledge,</li>
|
|
|
|
<li>Allows debugger of the Java source,</li>
|
|
|
|
<li>Resolves cross-browser issues,</li>
|
|
|
|
<li>Native code can be interleaved with Java,</li>
|
|
|
|
<li>Certain compile-time errors can be detected before execution.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>The key disadvantages of GWT are:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>Commercial support is not available from the developers,</li>
|
|
|
|
<li>The higher the level of abstraction, the more difficult it is
|
|
|
|
to implement features that go against the architecture and to debug
|
|
|
|
when things go wrong,</li>
|
|
|
|
<li>It's use may deter from learning and understanding JavaScript,
|
|
|
|
which is ultimately necessary to implement certain new features.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>In summary, consider GWT for simpler projects, but be careful of
|
|
|
|
placing to much emphasis on it as a tool that avoids having to learn
|
|
|
|
JavaScript properly.</p>
|
|
|
|
|
|
|
|
<h4><a name="native_js_frameworks"></a>Native JavaScript Frameworks
|
|
|
|
and Libraries</h4>
|
|
|
|
|
|
|
|
<p>Rather than list and compare every JavaScript framework, please
|
|
|
|
see the wikipedia entries for <a
|
|
|
|
href="http://en.wikipedia.org/wiki/List_of_JavaScript_libraries#JavaScript">web
|
|
|
|
application frameworks</a> and the <a
|
|
|
|
href="http://en.wikipedia.org/wiki/Comparison_of_JavaScript_frameworks">comparison
|
|
|
|
of JavaScript</a>. The comparison should not be considered authoritative,
|
|
|
|
more so it illustrates the types of features provided, such as event
|
|
|
|
handling, animation, widgets, AJAX request support etc. <a
|
|
|
|
href="http://javascriptlibraries.com/">This site</a> is also a useful
|
|
|
|
list of JavaScript libraries, mostly being open/free source licensed.</p>
|
|
|
|
|
|
|
|
<p>Be aware that many frameworks add implicit behaviours to make
|
|
|
|
JavaScript appear more like an OO language and to increase the base
|
|
|
|
functionality of the language. During the writing of the layout portion
|
|
|
|
of mxGraph, it was found that this implicit behaviour broke an example
|
|
|
|
in a very hard to debug manner. Be aware that this may cause
|
|
|
|
problems and if you select a framework ensure you understand which
|
|
|
|
implicit behaviours it introduces.</p>
|
|
|
|
|
|
|
|
<p>When selecting a framework and/or libraries think about which
|
|
|
|
frameworks tie you into certain functional behaviour and look for
|
|
|
|
libraries that provide features such as animation as distinct,
|
|
|
|
independent blocks, that you can use without being tied into the overall
|
|
|
|
design.</p>
|
|
|
|
|
|
|
|
<h4><a name="integration_js_frameworks"></a>Integration of mxGraph
|
|
|
|
and JavaScript frameworks</h4>
|
|
|
|
|
|
|
|
<p>This area is often misunderstood, put simply, there is no <em>integration</em>
|
|
|
|
required. Web applications generally comprise one or more <a
|
|
|
|
href="http://en.wikipedia.org/wiki/Span_and_div"><em>div</em></a>
|
|
|
|
elements into which the HTML wrapping the JavaScript of the application
|
|
|
|
is placed. If you create a div as a container for an mxGraph, that area
|
|
|
|
is a stand-alone display for the mxGraph application. It can communicate
|
|
|
|
itself with any back-end server, but there is no interdependence between
|
|
|
|
that div and the rest of the page, other than the area each take up.
|
|
|
|
This includes event handling, mxGraph can handle the events for its
|
|
|
|
container, even if the rest of the web page used a completely different
|
|
|
|
event model. As long as neither mxGraph nor the other libraries and
|
|
|
|
frameworks on the page introduce implicit behaviours that break one part
|
|
|
|
of the page, the issue of client integration is not something that needs
|
|
|
|
analysis.</p>
|
|
|
|
|
|
|
|
<p>Integration of the mxGraph back-end functionality, that which
|
|
|
|
sits at the server-side is the subject of a later chapter.</p>
|
|
|
|
|
|
|
|
<h4><a name="extending_mxgraph"></a>Extending mxGraph in JavaScript</h4>
|
|
|
|
|
|
|
|
<p>In JavaScript, there are various ways of mapping the Object
|
|
|
|
Oriented paradigm to language constructs. mxGraph uses a particular
|
|
|
|
scheme throughout the project, with the following implicit rules:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>Do not change the built-in prototypes</li>
|
|
|
|
<li>Donot try to limit the power of the JavaScript language.</li>
|
|
|
|
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>There are two types of “classes” in mxGraph; <EM>classes</em>
|
|
|
|
and <EM>singletons</em> (where only one instance of the class exists).
|
|
|
|
Singletons are mapped to global objects where the variable name is the
|
|
|
|
same as the class name. For example, mxConstants is an object with all
|
|
|
|
the constants defined as object fields. Normal classes are mapped to a
|
|
|
|
constructor function and a prototype which defines the instance fields
|
|
|
|
and methods. For example, mxEditor is a function and mxEditor.prototype
|
|
|
|
is the prototype for the object that the mxEditor function creates. The
|
|
|
|
<em>mx</em> prefix is a convention that is used for all classes in the
|
|
|
|
mxGraph package to avoid conflicts with other objects in the global
|
|
|
|
namespace.</p>
|
|
|
|
|
|
|
|
<p>For subclassing, the superclass must provide a constructor that
|
|
|
|
is either parameterless or handles an invocation with no arguments.
|
|
|
|
Furthermore, the special constructor field must be redefined after
|
|
|
|
extending the prototype. For example, the superclass of mxEditor is
|
|
|
|
mxEventSource. This is represented in JavaScript by first
|
|
|
|
“inheriting” all fields and methods from the superclass by
|
|
|
|
assigning the prototype to an instance of the superclass, eg.</p>
|
|
|
|
<pre>mxEditor.prototype = new mxEventSource()</pre>
|
|
|
|
<p>and redefining the constructor field using:</p>
|
|
|
|
|
|
|
|
<pre>mxEditor.prototype.constructor = mxEditor</pre>
|
|
|
|
|
|
|
|
<p>The latter rule is applied so that the type of an object can be
|
|
|
|
retrieved via the name of it’s constructor using <EM>mxUtils.getFunctionName(obj.constructor)</em>.</p>
|
|
|
|
|
|
|
|
<h5><a name="constructor"></a>Constructor</h5>
|
|
|
|
|
|
|
|
<p>For subclassing in mxGraph, the same mechanism should be applied.
|
|
|
|
For example, for subclassing the mxGraph class, first a constructor must
|
|
|
|
be defined for the new class. The constructor calls the super
|
|
|
|
constructor with any arguments that it may have using the <em>call</em>
|
|
|
|
function on the mxGraph function object, passing along explicitly each
|
|
|
|
argument:</p>
|
|
|
|
<pre>
|
|
|
|
function MyGraph(container)
|
|
|
|
{
|
|
|
|
mxGraph.call(this, container);
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>The prototype of MyGraph inherits from mxGraph as follows. As
|
|
|
|
usual, the constructor is redefined after extending the superclass:</p>
|
|
|
|
|
|
|
|
<pre>MyGraph.prototype = new mxGraph();
|
|
|
|
MyGraph.prototype.constructor = MyGraph;</pre>
|
|
|
|
|
|
|
|
<p>You may want to define the codec associated for the class after
|
|
|
|
the above code (see I/O section of manual). This code will be executed
|
|
|
|
at class loading time and makes sure the same codec is used to encode
|
|
|
|
instances of mxGraph and MyGraph.</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
var codec = mxCodecRegistry.getCodec(mxGraph);
|
|
|
|
codec.template = new MyGraph();
|
|
|
|
mxCodecRegistry.register(codec);
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<h5><a name="functions"></a>Functions</h5>
|
|
|
|
|
|
|
|
<p>In the prototype for MyGraph, functions of mxGraph can be
|
|
|
|
extended as follows.</p>
|
|
|
|
<pre>
|
|
|
|
MyGraph.prototype.isSelectable = function(cell)
|
|
|
|
{
|
|
|
|
var selectable = mxGraph.prototype.isSelectable.apply(this, arguments);
|
|
|
|
var geo = this.model.getGeometry(cell);
|
|
|
|
return selectable &&(geo == null || !geo.relative);
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>The supercall in the first line is optional. It is done using the
|
|
|
|
<em>apply</em> function on the <em>isSelectable</em> function object of
|
|
|
|
the mxGraph prototype, using the special <em>this</em> andn <em>arguments</em>
|
|
|
|
variables as parameters. Calls to the superclass function are only
|
|
|
|
possible if the function is not replaced in the superclass as follows,
|
|
|
|
which is another way of “subclassing” in JavaScript.</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
mxGraph.prototype.isSelectable = function(cell)
|
|
|
|
{
|
|
|
|
var geo = this.model.getGeometry(cell);
|
|
|
|
return selectable && (geo == null || !geo.relative);
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>The above scheme is useful if a function definition needs to be
|
|
|
|
replaced completely.</p>
|
|
|
|
<p>In order to add new functions and fields to the subclass, the
|
|
|
|
following code is used. The example below adds a new function to return
|
|
|
|
the XML representation of the graph model:</p>
|
|
|
|
<pre>
|
|
|
|
MyGraph.prototype.getXml = function()
|
|
|
|
{
|
|
|
|
var enc = new mxCodec();
|
|
|
|
return enc.encode(this.getModel());
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<h5><a name="fields"></a>Fields</h5>
|
|
|
|
<p>Likewise, a new field is declared and defined as follows:</p>
|
|
|
|
<pre>
|
|
|
|
MyGraph.prototype.myField = ‘Hello, World!’;
|
|
|
|
</pre>
|
|
|
|
<p>Note that the value assigned to myField is created only once,
|
|
|
|
that is, all instances of MyGraph share the same value. If you require
|
|
|
|
instance-specific values, then the field must be defined in the
|
|
|
|
constructor instead. For example:</p>
|
|
|
|
<pre>
|
|
|
|
function MyGraph(container)
|
|
|
|
{
|
|
|
|
mxGraph.call(this, container);
|
|
|
|
this.myField = [];
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
<p>Finally, a new instance of MyGraph is created using the following
|
|
|
|
code, where container is a DOM node that acts as a container for the
|
|
|
|
graph view:</p>
|
|
|
|
<pre>
|
|
|
|
var graph = new MyGraph(container);
|
|
|
|
</pre>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<h3><a name="general_javascript"></a>General JavaScript Development</h3>
|
|
|
|
|
|
|
|
<h4><a name="development_environments"></a>JavaScript Development
|
|
|
|
Environments</h4>
|
|
|
|
<p>Please refer to the <a
|
|
|
|
href="http://extjs.com/learn/Manual:Resources#IDEs">ExtJS manual
|
|
|
|
entry</a> on the subject.</p>
|
|
|
|
|
|
|
|
<h4><a name="debugging_javascript"></a>Debugging JavaScript</h4>
|
|
|
|
<p>Please refer to the <a
|
|
|
|
href="http://en.wikipedia.org/wiki/JavaScript#Debugging">wikipedia
|
|
|
|
entry</a>, or to the <a
|
|
|
|
href="http://extjs.com/learn/Manual:Resources#Various_debugging_tools">ExtJS
|
|
|
|
manual entry</a>, for information on the subject.</p>
|
|
|
|
|
|
|
|
<h4><a name="javascript_obfuscation"></a>JavaScript Obfuscation</h4>
|
|
|
|
<p>By default, when you deliver JavaScript to a browser client, you
|
|
|
|
deliver the entire source to that JavaScript. That JavaScript is then
|
|
|
|
interpreted and run on the browser. It is not possible to encrypt the
|
|
|
|
JavaScript to any extent on the client at the point it is run, since the
|
|
|
|
JavaScript source must be understood by the JavaScript interpretor and
|
|
|
|
interpreted languages do not have a binary intermediate form.</p>
|
|
|
|
|
|
|
|
<p>It would be possible to encrypt the JavaScript in transmission
|
|
|
|
and have it decrypted and run on the client, but the client would still
|
|
|
|
be able to access the source after decryption.</p>
|
|
|
|
|
|
|
|
<p>We do not obfuscate because the method names form a public API
|
|
|
|
and I/O would need to understand the obfuscation at both communication
|
|
|
|
ends.</p>
|
|
|
|
|
|
|
|
<h4><a name="namespaces"></a>Namespaces</h4>
|
|
|
|
<p>The concept of namespaces does not exist in JavaScript, so take
|
|
|
|
great care when creating new class names. In mxGraph, all of the classes
|
|
|
|
begin with the prefix “mx-”, to avoid clashes or overriding
|
|
|
|
prototypes unintentionally. Prior to starting your application it is
|
|
|
|
worth creating a prefix particular to your application that you append
|
|
|
|
to all of the your classes to create a manual “namespace”.</p>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
<h2><a name="hello_world"></a>Hello World!</h2>
|
|
|
|
<p>Hello World in mxGraph consists of a simple client-side example
|
|
|
|
that displays two connected vertices with the labels “Hello”
|
|
|
|
and “World!”. The example demonstrates the following things:
|
|
|
|
</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li><strong>Creating an HTML page that links the mxGraph
|
|
|
|
client JavaScript,</strong></li>
|
|
|
|
<li><strong>Creating a container to place the mxGraph
|
|
|
|
into,</strong></li>
|
|
|
|
<li><strong>Adds the required cells to that graph.</strong></li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>The source code for the example, helloworld.html, can be found
|
|
|
|
below and in the examples directory of both the evaluation and full
|
|
|
|
versions of mxGraph. The HTML source contains two main sections, the
|
|
|
|
head and the body. These contain the following main elements that you
|
|
|
|
can consider a template for building a basic mxGraph application:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li><strong>mxBasePath</strong>: This is a JavaScript variable
|
|
|
|
that defines the directory within which the css, images, resources and js
|
|
|
|
directories are expected to be found. It is JavaScript code and needs
|
|
|
|
to be placed with in a <em>script</em> tag. This must come before the
|
|
|
|
line loading mxClient.js and should not have a trailing slash.</li>
|
|
|
|
|
|
|
|
<li><strong>mxClient.js</strong>: This is the path to mxGraph
|
|
|
|
library. If the HTML file is executed locally, the path might be local
|
|
|
|
to the computer or a public Internet path. If the html page were
|
|
|
|
downloaded from a web server, the path would generally be a public
|
|
|
|
Internet path.</li>
|
|
|
|
|
|
|
|
<li><strong>Creation of the container</strong>: At the bottom of
|
|
|
|
the code, in the body element, the function that is called on loading
|
|
|
|
the web page is defined (the value of onload). It passes in a div
|
|
|
|
container as a parameter, that is defined underneath. This div is the
|
|
|
|
container the mxGraph component will be placed within. In this example
|
|
|
|
a grid background is applied, as commonly used in diagramming
|
|
|
|
applications. No other part of the graph visuals are described at
|
|
|
|
container creation, other than the background and the container width
|
|
|
|
and height.
|
|
|
|
|
|
|
|
<p>Note that the overflow:hidden style should always be used if you
|
|
|
|
want no scrollbars to appear.</p>
|
|
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li><strong>The entry function</strong>: The main code of the file
|
|
|
|
is the entry method executed on page load in this case. This is
|
|
|
|
JavaScript code and must be within a JavaScript <em>script</em>
|
|
|
|
element. The first lines of any mxGraph application should be to check
|
|
|
|
the browser is supported and exit appropriately if not. If the browser
|
|
|
|
is supported, a mxGraph is created within the div container and three
|
|
|
|
cells are added to the graph between the begin/end update calls.</li>
|
|
|
|
</ul>
|
|
|
|
<br/>
|
|
|
|
<p><img src="images/mx_man_hello_world.png" name="ill_hello_world" />
|
|
|
|
<br/>
|
|
|
|
<em>The mxGraph HelloWorld example</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<title>Hello, World! example for mxGraph</title>
|
|
|
|
|
|
|
|
<!-- Sets the <U>basepath</U> for the library if not in same directory -->
|
|
|
|
<script type=<em>"text/javascript"</em>>
|
|
|
|
mxBasePath = '../src';
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<!-- Loads and <U>initializes</U> the library -->
|
|
|
|
<script type=<em>"text/javascript"</em> src=<em>"../src/js/mxClient.js"</em>></script>
|
|
|
|
|
|
|
|
<!-- Example code -->
|
|
|
|
<script type=<em>"text/javascript"</em>>
|
|
|
|
// Program starts here. Creates a sample graph in the
|
|
|
|
// DOM node with the specified ID. This function is invoked
|
|
|
|
// from the onLoad event handler of the document (see below).
|
|
|
|
function main(container)
|
|
|
|
{
|
|
|
|
// Checks if the browser is supported
|
|
|
|
if (!mxClient.isBrowserSupported())
|
|
|
|
{
|
|
|
|
mxUtils.error('Browser is not supported!', 200, false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Creates the graph inside the given container
|
|
|
|
var graph = new mxGraph(container);
|
|
|
|
|
|
|
|
// Enables rubberband selection
|
|
|
|
new mxRubberband(graph);
|
|
|
|
|
|
|
|
// Gets the default parent for inserting new cells. This
|
|
|
|
// is normally the first child of the root (ie. layer 0).
|
|
|
|
var parent = graph.getDefaultParent();
|
|
|
|
|
|
|
|
// Adds cells to the model in a single step
|
|
|
|
graph.getModel().beginUpdate();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var v1 = graph.insertVertex(parent, null,
|
|
|
|
'Hello,', 20, 20, 80, 30);
|
|
|
|
var v2 = graph.insertVertex(parent, null,
|
|
|
|
'World!', 200, 150, 80, 30);
|
|
|
|
var e1 = graph.insertEdge(parent, null, '', v1, v2);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
// Updates the display
|
|
|
|
graph.getModel().endUpdate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
</script>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<!-- Page passes the container for the graph to the program -->
|
|
|
|
<body onload=<em>"main(document.getElementById('graphContainer'))"</em>>
|
|
|
|
|
|
|
|
<!-- Creates a container for the graph with a grid wallpaper -->
|
|
|
|
<div id=<em>"graphContainer"</em>
|
|
|
|
style=<em>"overflow:hidden;width:321px;height:241px;background:url('editors/images/grid.gif')"</em>>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
</html>
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>Important concepts to note in this exercise are:</p>
|
|
|
|
<ul>
|
|
|
|
<li>mxClient.js is a JavaScript file combining all of the
|
|
|
|
JavaScript source code of mxGraph. When downloading from a web server,
|
|
|
|
obtaining all the JavaScript as one file is much faster than as lots of
|
|
|
|
separate files, due to the overhead of the requests/acknowledgements
|
|
|
|
required for each file. The speed increase is usually at least x2,
|
|
|
|
although it varies with the capacity of the server to have parallel
|
|
|
|
sockets open with one client.</li>
|
|
|
|
<li>The JavaScript code and its dependencies are all placed within
|
|
|
|
the <em>head</em> element.</li>
|
|
|
|
<li>Internet Explorer has, by default, security options enabled
|
|
|
|
that cause a user prompt when attempting to run JavaScript from the
|
|
|
|
local file system. This can be disabled in the options menu, but note
|
|
|
|
that running from the local file system is not a deployment scenario of
|
|
|
|
mxGraph, this would only happen during development.</li>
|
|
|
|
<li>Your application can be written and linked into the
|
|
|
|
application either within the HTML file, or in separate JavaScript
|
|
|
|
source code that is linked into the html in the way the mxClient.js
|
|
|
|
file is in the example.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<h2><a name="deployment"></a>mxGraph Deployment and Debugging</h2>
|
|
|
|
|
|
|
|
<p>There are two versions of the mxclient.js file, one for production use and
|
|
|
|
a second for development/debugging use. <em>javascript/src/js/mxClient.js</em> is
|
|
|
|
the production version and <em>javascript/debug/js/mxClient.js</em> is for
|
|
|
|
development. The first version has all linefeeds stripped to ensure the
|
|
|
|
file is the minimal size possible. This has the side-effect of breaking most
|
|
|
|
JavaScript debuggers. During development you are advised to use the debug
|
|
|
|
version, which has the linefeeds in, enabling debugging in the supported
|
|
|
|
browsers.</p>
|
|
|
|
|
|
|
|
<p>Both mxClient.js files are the entire JavaScript source to mxGraph,
|
|
|
|
with all of the whitespace and comments removed to reduce file size.
|
|
|
|
Whilst debugging, it is easier to use the individual source files if you
|
|
|
|
need to debug into the mxGraph library itself. The source code version of
|
|
|
|
mxGraph contains the full source in the source.zip file in the
|
|
|
|
<em>javascript/devel</em> directory. Unzipping this into the mxBasePath and removing
|
|
|
|
the load of the complete mxClient.js file enables easier debugging of mxGraph.
|
|
|
|
Note that the mxclient.js file in the source zip is a bootstrap file that
|
|
|
|
loads all the other JavaScript source code.</p>
|
|
|
|
|
|
|
|
<p>The download speed of the client source can be further improved
|
|
|
|
by compressing the code. All modern browsers support receiving and
|
|
|
|
uncompressing transmissions compressed at the server end and all good
|
|
|
|
web servers support detection of those browser that do not support it
|
|
|
|
and send the uncompressed version as a fallback.</p>
|
|
|
|
|
|
|
|
<p>For example, on the Apache web server there is a mod_deflate
|
|
|
|
module, details of its use can be found from a standard search. The
|
|
|
|
jgraph.com server uses this module and there have been no reports of
|
|
|
|
issues in any supported browser.</p>
|
|
|
|
|
|
|
|
<p>The use of compression reduces the mxClient.js file size down
|
|
|
|
from about 600KB to around 130KB. The difference is not noticed by the
|
|
|
|
user on most modern networks, but there might be situations where the
|
|
|
|
smaller version would be preferable.</p>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
<h1><a name="model_cells"></a>mxGraph Model and Cells</h1>
|
|
|
|
|
|
|
|
<h2><a name="mxgraph_architecture"></a>Core mxGraph architecture</h2>
|
|
|
|
|
|
|
|
<h3><a name="mxgraph_model"></a>The mxGraph Model</h3>
|
|
|
|
|
|
|
|
<p>The mxGraph model is the core model that describes the structure
|
|
|
|
of the graph, the class is called mxGraphModel and is found within the
|
|
|
|
model package. Additions, changes and removals to and from the graph
|
|
|
|
structure take place through the graph model API. The model also
|
|
|
|
provides methods to determine the structure of the graph, as well as
|
|
|
|
offering methods to set visual states such as visibility, grouping and
|
|
|
|
style.</p>
|
|
|
|
|
|
|
|
<p>However, although the transactions to the model are stored on the
|
|
|
|
model, mxGraph is designed in such a way that the main public API is
|
|
|
|
through the mxGraph class. The concept of “add this cell to the
|
|
|
|
graph” is a more natural description of the action than “add
|
|
|
|
this cell to the model of the graph”. Where it is intuitive,
|
|
|
|
functions available on the model and cells are duplicated on the graph
|
|
|
|
and those methods on the graph class are considered the main public API.
|
|
|
|
Throughout the rest of this manual these key API methods are given a pink background:</p>
|
|
|
|
<div id="coreapi">
|
|
|
|
<p>anExampleCoreAPIMethod()</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p>So, though many of the main API calls are through the mxGraph
|
|
|
|
class, keep in mind that mxGraphModel is the underlying object that
|
|
|
|
stores the data structure of your graph.</p>
|
|
|
|
|
|
|
|
<p>mxGraph uses a transactional system for making changes to the
|
|
|
|
model. In the HelloWorld example we saw this code:</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
// Adds cells to the model in a single step
|
|
|
|
graph.getModel().beginUpdate();
|
|
|
|
try
|
|
|
|
{
|
|
|
|
var v1 = graph.addVertex(parent, null, 'Hello,', 20, 20, 80, 30);
|
|
|
|
var v2 = graph.addVertex(parent, null, 'World!', 200, 150, 80, 30);
|
|
|
|
var e1 = graph.addEdge(parent, null, '', v1, v2);
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
// Updates the display
|
|
|
|
graph.getModel().endUpdate();
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>to perform the insertion of the 2 vertices and 1 edge. For each
|
|
|
|
change to the model you make a call to beginUpdate(), make the
|
|
|
|
appropriate calls to change the model, then call endUpdate() to finalize
|
|
|
|
the changes and have the change event notifications sent out.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Key API Methods:</strong></p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li><strong>mxGraphModel.beginUpdate() </strong>- starts a new
|
|
|
|
transaction or a sub-transaction.</li>
|
|
|
|
<li><strong>mxGraphModel.endUpdate()</strong> - completes a
|
|
|
|
transaction or a sub-transaction.</li>
|
|
|
|
<li><strong>mxGraph.addVertex()</strong> - Adds a new vertex to
|
|
|
|
the specified parent cell.</li>
|
|
|
|
<li><strong>mxGraph.addEdge()</strong> - Adds a new edge to the
|
|
|
|
specified parent cell.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p><strong>Note</strong> – Technically you do not have to
|
|
|
|
surround your changes with the begin and end update calls. Changes made
|
|
|
|
outside of this update scope take immediate effect and send out the
|
|
|
|
notifications immediately. In fact, changes within the update scope
|
|
|
|
enact on the model straight away, the update scope is there to control
|
|
|
|
the timing and concatenation of event notifications. Unless the update
|
|
|
|
wrapping causes code aesthetic issues, it is worth using it by habit to
|
|
|
|
avoid possible problems with event and undo granularity.</p>
|
|
|
|
|
|
|
|
<p>Note the way in which the model changes are wrapped in a try
|
|
|
|
block and the endUpdate() in a finally block. This ensures the update is
|
|
|
|
completed, even if there is an error in the model changes. You should
|
|
|
|
use this pattern wherever you perform model changes for ease of
|
|
|
|
debugging.</p>
|
|
|
|
|
|
|
|
<p>Ignore the reference to the parent cell for now, that will be
|
|
|
|
explained later in this chapter.</p>
|
|
|
|
|
|
|
|
<h3><a name="transaction_model"></a>The Transaction Model</h3>
|
|
|
|
|
|
|
|
<p>The sub-transaction in the blue block above refers to the fact
|
|
|
|
that transactions can be nested. That is, there is a counter in the
|
|
|
|
model that increments for every <em>beginUpdate</em> call and decrements
|
|
|
|
for every <em>endUpdate</em> call. After increasing to at least 1, when
|
|
|
|
this count reaches 0 again, the model transaction is considered complete
|
|
|
|
and the event notifications of the model change are fired.</p>
|
|
|
|
|
|
|
|
<p>This means that every sub-contained section of code can (and
|
|
|
|
should) be surrounded by the begin/end combination. This provide the
|
|
|
|
ability in mxGraph to create separate transactions that be used as
|
|
|
|
“library transactions”, the ability to create compound
|
|
|
|
changes and for one set of events to be fired for all the changes and
|
|
|
|
only one undo created. Automatic layouting is a good example of where
|
|
|
|
the functionality is required.</p>
|
|
|
|
|
|
|
|
<p>In automatic layouting, the user makes changes to the graph,
|
|
|
|
usually through the user interface, and the application automatically
|
|
|
|
positions the result according to some rules. The automatic positioning,
|
|
|
|
the layouting, is a self-contained algorithm between begin/end update
|
|
|
|
calls that has no knowledge of the specifics of the change. Because all
|
|
|
|
changes within the begin/end update are made directly to the graph
|
|
|
|
model, the layout can act upon the state of the model as the change is
|
|
|
|
in progress.</p>
|
|
|
|
|
|
|
|
<p>It is important to distinguish between functionality that acts on
|
|
|
|
the graph model as part of a compound change and functionality that
|
|
|
|
reacts to atomic graph change events. In the first case, such as for
|
|
|
|
automatic layouting, the functionality takes the model as-is and acts
|
|
|
|
upon it. This method should only be used for parts of compound model
|
|
|
|
changes. All other parts of the application should only react to model
|
|
|
|
change events.</p>
|
|
|
|
|
|
|
|
<p>Model change events are fired when the last endUpdate call
|
|
|
|
reduces the counter back down to 0 and indicate that at least one atomic
|
|
|
|
graph change has occurred. The change event contains complete
|
|
|
|
information as to what has altered (see later section on <strong>Events</strong>
|
|
|
|
for more details).</p>
|
|
|
|
|
|
|
|
<h4><a name="model_change_methods"></a>The Model Change Methods</h4>
|
|
|
|
|
|
|
|
<p>Below is a list of the methods that alter the graph model and
|
|
|
|
should be placed, directly or indirectly, with the scope of an update:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>add(parent, child, index)</li>
|
|
|
|
<li>remove(cell)</li>
|
|
|
|
<li>setCollapsed(cell, collapsed)</li>
|
|
|
|
<li>setGeometry(cell, geometry)</li>
|
|
|
|
<li>setRoot(root)</li>
|
|
|
|
<li>setStyle(cell, style)</li>
|
|
|
|
<li>setTerminal(cell, terminal, isSource)</li>
|
|
|
|
<li>setTerminals(edge,source,target)</li>
|
|
|
|
<li>setValue(cell, value)</li>
|
|
|
|
<li>setVisible(cell, visible)</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>Initially, we will just concern ourselves with the add and
|
|
|
|
remove, as well as the geometry and style editing methods. Note that
|
|
|
|
these are not core API methods, as usual these methods are on the
|
|
|
|
mxGraph class, where appropriate, and they perform the update
|
|
|
|
encapsulation for you.</p>
|
|
|
|
|
|
|
|
<p><em>Design Background</em> - Some people are confused by the
|
|
|
|
presence of visual information being stored by the model. These
|
|
|
|
attributes comprise cell positioning, visibility and collapsed state.
|
|
|
|
The model stores the default state of these attributes, providing a
|
|
|
|
common place to set them on a per-cell basis, whereas, views can
|
|
|
|
override the values on a per-view basis. The model is simply the first
|
|
|
|
common place in the architecture where these attributes can be set on a
|
|
|
|
global basis. Remember, this is a graph <em>visualization</em> library,
|
|
|
|
the visualization part is the core functionality.</p>
|
|
|
|
|
|
|
|
<h5><a name="inserting_cells"></a>Inserting Cells</h5>
|
|
|
|
|
|
|
|
<p>The three graph cells created in the <CODE>HelloWorld</CODE>
|
|
|
|
application are two vertices and one edge connecting the vertices. If
|
|
|
|
you are not familiar with basic graph theory and its terminology, please
|
|
|
|
see the <a href="http://en.wikipedia.org/wiki/Graph_theory">wikipedia
|
|
|
|
entry</a>.</p>
|
|
|
|
|
|
|
|
<p>You can add vertices and edges using the add() method on the
|
|
|
|
model. However, for the purposes of general usage of this library, learn
|
|
|
|
that mxGraph.insertVertex() and mxGraph.insertEdge() are the core public
|
|
|
|
API for adding cells. The function of the model requires that the cell
|
|
|
|
to be added is already created, whereas the mxGraph.insertVertex()
|
|
|
|
creates the cell for you.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API functions:</strong></p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li><strong>mxGraph.insertVertex(</strong><strong>parent,
|
|
|
|
id, value, x, y, width, height, style</strong><strong>)</strong> – creates
|
|
|
|
and inserts a new vertex into the model, within a begin/end update
|
|
|
|
call.</li>
|
|
|
|
<li><strong>mxGraph.insertEdge(</strong><strong>parent,
|
|
|
|
id, value, source, target, style</strong><strong>)</strong><strong>
|
|
|
|
– </strong>creates and inserts a new edge into the model, within a
|
|
|
|
begin/end update call.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p><code>mxGraph.insertVertex()</code> will create an mxCell object
|
|
|
|
and return it from the method used. The parameters of the function are:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li><strong>parent</strong> – the cell which is the immediate
|
|
|
|
parent of the new cell in the group structure. We will address the
|
|
|
|
group structure shortly, but for now use <code>graph.getDefaultParent();</code>
|
|
|
|
as your default parent, as used in the HelloWorld example.</li>
|
|
|
|
|
|
|
|
<li><strong>id</strong> – this is a global unique identifier
|
|
|
|
that describes the cell, it is always a string. This is primarily for
|
|
|
|
referencing the cells in the persistent output externally. If you do not
|
|
|
|
wish to maintain ids yourself, pass null into this parameter and ensure
|
|
|
|
that mxGraphModel.isCreateIds() returns true. This way the model will
|
|
|
|
manage the ids and ensure they are unique.</li>
|
|
|
|
|
|
|
|
<li><strong>value</strong> – this is the user object of the
|
|
|
|
cell. User object are simply that, just objects, but form the objects
|
|
|
|
that allow you to associate the business logic of an application with
|
|
|
|
the visual representation of mxGraph. They will be described in more
|
|
|
|
detail later in this manual, however, to start with if you use a string
|
|
|
|
as the user object, this will be displayed as the label on the vertex or
|
|
|
|
edge.</li>
|
|
|
|
|
|
|
|
<li><strong>x, y, width, height</strong> – as the names
|
|
|
|
suggest, these are the x and y position of the top left corner of the
|
|
|
|
vertex and its width and height.</li>
|
|
|
|
|
|
|
|
<li><strong>style</strong> – the style description to be
|
|
|
|
applied to this vertex. Styles will be described in more detail shortly,
|
|
|
|
but at a simple level this parameter is a string that follows a
|
|
|
|
particular format. In the string appears zero or more style names and
|
|
|
|
some number of key/value pairs that override the global style or set a
|
|
|
|
new style. Until we create custom styles, we will just use those
|
|
|
|
currently available.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>With the edge addition method, the identically named parameters
|
|
|
|
perform the same function as in the vertex addition method. The source
|
|
|
|
and target parameters define the vertices to which the edge is
|
|
|
|
connected. Note that the source and target vertices should already have
|
|
|
|
been inserted into the model.</p>
|
|
|
|
|
|
|
|
<h3><a name="mxcell"></a>mxCell</h3>
|
|
|
|
|
|
|
|
<p>mxCell is the cell object for both vertices and edges. mxCell
|
|
|
|
duplicates many of the functions available in the model. The key
|
|
|
|
difference in usage is that using the model methods creates the
|
|
|
|
appropriate event notifications and undo, using the cell makes the
|
|
|
|
change but there is no record of the change. This can be useful for
|
|
|
|
temporary visual effects such as animations or changes on a mouse over,
|
|
|
|
for example. As a general rule though, use the model editing API unless
|
|
|
|
you encounter a specific problem with this mechanism.</p>
|
|
|
|
|
|
|
|
<p>When creating a new cell, three things are required in the
|
|
|
|
constructor, a value (user object), a geometry and a style. We will now
|
|
|
|
explore these 3 concepts before returning to the cell.</p>
|
|
|
|
|
|
|
|
<h4><a name="styles"></a>Styles</h4>
|
|
|
|
|
|
|
|
<p>The concept of styles and stylesheets in conceptually similar to
|
|
|
|
CSS stylesheets, though note that CSS are actually used in mxGraph, but
|
|
|
|
only to affect global styles in the DOM of the HTML page. Open up the
|
|
|
|
util.mxConstants.js file in your editor and search for the first match
|
|
|
|
on “STYLE_”. If you scroll down you will see a large number
|
|
|
|
of strings defined for all the various styles available with this
|
|
|
|
prefix. Some of styles apply to vertices, some to edges and some to
|
|
|
|
both. As you can see, these define visual attributes on the element they
|
|
|
|
act upon.</p>
|
|
|
|
|
|
|
|
<p>The mxStylesheet holds one object, styles, which is a hashtable
|
|
|
|
mapping style names to an array of styles:</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_styles.png" name="graphics5"/><br/>
|
|
|
|
<em>Style arrays within the styles collection</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>In the above image the blue box represents the styles hashtable
|
|
|
|
in mxStyleSheet. The string 'defaultVertex' is the key to an array of
|
|
|
|
string/value pairs, which are the actual styles. Note that mxGraph
|
|
|
|
creates two default styles, one for vertices and one for edges. If you
|
|
|
|
look back to the helloworld example, no style was passed into the
|
|
|
|
optional style parameter of insertVertex or insertEdge. In this case the
|
|
|
|
default style would be used for those cells.</p>
|
|
|
|
|
|
|
|
<h5><a name="setting_cell_style"></a>Setting the Style of a Cell</h5>
|
|
|
|
|
|
|
|
<p>If you wanted to specify a style other than the default for a
|
|
|
|
cell, you must pass that new style either to the cell when it is created
|
|
|
|
(mxGraph's insertVertex and insertEdge both have an optional parameter
|
|
|
|
for this) or pass that style to the cell using model.setStyle().</p>
|
|
|
|
|
|
|
|
<p>The style that you pass has the form stylename. ,note that the
|
|
|
|
stylenames and key/value pairs may be in any order. Below are examples
|
|
|
|
to demonstrate this concept, adapting the insertVertex call we saw in
|
|
|
|
helloworld:</p>
|
|
|
|
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
<p>A new style called 'ROUNDED' has been created, to apply this to
|
|
|
|
a vertex:</p>
|
|
|
|
<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'ROUNDED');</pre>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li>
|
|
|
|
<p>To create a new vertex with the ROUNDED style, overriding the
|
|
|
|
stroke and fill colors:</p>
|
|
|
|
<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'ROUNDED;strokeColor=red;fillColor=green');</pre>
|
|
|
|
</li>
|
|
|
|
|
|
|
|
<li>
|
|
|
|
<p>To create a new vertex with no global style, but with local
|
|
|
|
stroke and fill colors:</p>
|
|
|
|
<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, ';strokeColor=red;fillColor=green');</pre>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<p>To create a vertex that uses the defaultVertex style, but a
|
|
|
|
local value of the fill color:</p>
|
|
|
|
<pre>var v1 = graph.insertVertex(parent, null, 'Hello', 20, 20, 80, 30, 'defaultVertex;fillColor=blue');</pre>
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
<p>Note that default style must be explicitly named in this case,
|
|
|
|
missing the style out sets no global style on the cell when the
|
|
|
|
semi-colon starts the string. If the string starts with no semi-colon,
|
|
|
|
the default style is used.</p>
|
|
|
|
|
|
|
|
<p>Again, the mxGraph class provides utility functions that form the
|
|
|
|
core API for accessing and changing the styles of cells:</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API functions:</strong></p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
|
|
<strong>mxGraph.setCellStyle(style, cells)</strong> – Sets
|
|
|
|
the style for the array of cells, encapsulated in a begin/end update.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<strong>mxGraph.getCellStyle(cell)</strong> – Returns the
|
|
|
|
style for the specified cell, merging the styles from any local style
|
|
|
|
and the default style for that cell type.
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<h5><a name="new_global_style"></a>Creating a New Global Style</h5>
|
|
|
|
<p>To create the ROUNDED global style described above, you can
|
|
|
|
follow this template to create a style and register it with
|
|
|
|
mxStyleSheet:</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
var style = new Object();
|
|
|
|
style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_RECTANGLE;
|
|
|
|
style[mxConstants.STYLE_OPACITY] = 50;
|
|
|
|
style[mxConstants.STYLE_FONTCOLOR]= '#774400';
|
|
|
|
graph.getStylesheet().putCellStyle('ROUNDED',style);
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<h4><a name="geometry"></a>Geometry</h4>
|
|
|
|
|
|
|
|
<p>In the helloworld example we saw the position and size of the
|
|
|
|
vertices passed into the insertVertex function. The coordinate system in
|
|
|
|
JavaScript is x is positive to the right and y is positive downwards,
|
|
|
|
and in terms of the graph, the positioning is absolute to the container
|
|
|
|
within which the mxGraph is placed.</p>
|
|
|
|
|
|
|
|
<p>The reason for a separate mxGeometry class, as opposed to simply
|
|
|
|
having the mxRectangle class store this information, is that the edges
|
|
|
|
also have geometry information.</p>
|
|
|
|
|
|
|
|
<p>The width and height values are ignored for edges and the x and y
|
|
|
|
values relate to the positioning of the edge label. In addition, edges
|
|
|
|
have the concept of control points. These are intermediate points along
|
|
|
|
the edge that the edge is drawn as passing through. The use of control
|
|
|
|
points is sometimes referred to as <strong>edge routing</strong>.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_edge_routing.png" name="ill_edge_routing"/><br/>
|
|
|
|
<em>An edge routed by 2 control points</em></p>
|
|
|
|
|
|
|
|
<p>There are two more important additional concepts in geometry,
|
|
|
|
relative positioning and offsets</p>
|
|
|
|
|
|
|
|
<h5><a name="relative_positioning"></a>Relative Positioning</h5>
|
|
|
|
|
|
|
|
<p>By default, the x and y position of a vertex is the offset of the
|
|
|
|
top left point of the bounding rectangle of the parent to the top left
|
|
|
|
point of the bounding rectangle of the cell itself. The concept of
|
|
|
|
parents and groups is discussed later in this chapter, but without going
|
|
|
|
into too much detail, if a cell does not have cell parent, the graph
|
|
|
|
container is its parent for positioning purposes.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_non_relative_pos.png"
|
|
|
|
name="ill_non_realtive_pos"/><br/>
|
|
|
|
<em>Non-relative vertex positioning</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
|
|
|
|
<p>For an edge, in non-relative mode, which is the default mode, the
|
|
|
|
edge label position is the absolute offset from the graph origin.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_non_realtive_edge_pos.png"
|
|
|
|
name="ill_non_rel_edge_pos"/><br/>
|
|
|
|
<em>Non-relative edge label positioning</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
|
|
|
|
<p>For vertices in relative mode, (x,y) is the proportion along the
|
|
|
|
parent cell's (width, height) where the cell's origin lies. (0,0) is the
|
|
|
|
same origin as the parent, (1,1) places the origin at the bottom right
|
|
|
|
corner of the parent. The same relative positioning extends below 0 and
|
|
|
|
above 1 for both dimensions. This positioning is useful for keeping
|
|
|
|
child cells fixed relative to the overall parent cell size.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_rel_vert_pos.png" name="rel_vert_pos"/><br/>
|
|
|
|
<em>Relative vertex positions</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>Lastly, edge labels in relative mode are palced based on the
|
|
|
|
positioning from the center of the edge. The x-coordinate is the
|
|
|
|
relative distance from the source end of the edge, at -1, to the target
|
|
|
|
end of the edge, at 1. The y co-ordinate is the pixel offset orthogonal
|
|
|
|
from the edge. The diagram below shows the values of x,y for various
|
|
|
|
edge labels in relative mode. Note that for a straight edge, the
|
|
|
|
calculations are simple. For edges with multiple control points, the
|
|
|
|
edge has to be traced along its segments (a segment being the line
|
|
|
|
between end points and/or control points) to find the correct distance
|
|
|
|
along the edge. The y value is the orthogonal offset from that segment.</p>
|
|
|
|
|
|
|
|
<p>Switching relative positioning on for edge labels is a common
|
|
|
|
preference for applications. Navigate to the mxGraph.insertEdge()
|
|
|
|
function in mxGraph, you will see this calls createEdge(). In
|
|
|
|
createEdge() the geometry is set relative for every edge created using
|
|
|
|
this prototype. This is partly the reason for the amount of helper
|
|
|
|
functions in mxGraph, they enable easy changing of the default
|
|
|
|
behaviour. You should try to use the mxGraph class API as much as
|
|
|
|
possible to provide this benefit in your applications.</p>
|
|
|
|
|
|
|
|
<h5><a name="offsets"></a>Offsets</h5>
|
|
|
|
|
|
|
|
<p>The offset field in mxGeometry is an absolute x,y offset applied
|
|
|
|
to the cell <strong>label</strong>. In the case of edge labels, the
|
|
|
|
offset is always applied after the edge label has been calculated
|
|
|
|
according to the relative flag in the above section.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API functions:</strong></p>
|
|
|
|
|
|
|
|
<ul><li><strong>mxGraph.resizeCell(cell, bounds)</strong> – Resizes
|
|
|
|
the specified cell to the specified bounds, within a begin/end update
|
|
|
|
call.</li>
|
|
|
|
<li><strong>mxGraph.resizeCells(cells, bounds)</strong> –
|
|
|
|
Resizes each of the cells in the cells array to the corresponding entry
|
|
|
|
in the bounds array, within a begin/end update call.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<h4><a name="user_objects"></a>User Objects</h4>
|
|
|
|
|
|
|
|
<p>The User object is what gives mxGraph diagrams a context, it
|
|
|
|
stores the business logic associated with a visual cell. In the
|
|
|
|
HelloWorld example the user object has just been a string, in this case
|
|
|
|
it simply represents the label that will be displayed for that cell. In
|
|
|
|
more complex applications, these user objects will be objects instead.
|
|
|
|
Some attribute of that object will generally be the label that the
|
|
|
|
visual cell will display, the rest of the object describes logic
|
|
|
|
relating to the application domain.</p>
|
|
|
|
|
|
|
|
<p>Using the example of a simple workflow or process application,
|
|
|
|
say we have the graph below (<a
|
|
|
|
href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">this
|
|
|
|
example is available online</a>, select the Swimlanes example from the tasks
|
|
|
|
window):</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_simple_workflow.png"
|
|
|
|
name="ill_simple_workflow"/><br/>
|
|
|
|
<em>A simple workflow</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>Typically, this workflow will exist on some application server
|
|
|
|
and/or database. The browser user connects to that server, or some
|
|
|
|
front-end server linked to the application server and the user's web
|
|
|
|
application requests the “order” workflow. The server
|
|
|
|
obtains the data of that workflow and transmits it to the client.</p>
|
|
|
|
|
|
|
|
<p>mxGraph supports the process of populating the model on the
|
|
|
|
server-side and transmitting to the client, and back again. See the
|
|
|
|
later chapter on “I/O and Server Communication”.</p>
|
|
|
|
|
|
|
|
<p>The data transmitted will be both the visual model (the diagram)
|
|
|
|
as well as the business logic (mostly contained in the user objects).
|
|
|
|
The client will initially show the diagram above. If the user has
|
|
|
|
permission to edit this workflow they will normally be able to do two
|
|
|
|
things, 1) edit the diagram, add and remove vertices, as well as
|
|
|
|
changing the connections, and 2) edit the user objects of the cells
|
|
|
|
(vertices and/or edges).</p>
|
|
|
|
|
|
|
|
<p>In the online demo, if you right click and select properties of
|
|
|
|
the “Check Inventory” diamond you will see this dialog:</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_vertex_props.png" name="ill_vertex_props"/><br/>
|
|
|
|
<em>The properties of a vertex</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>These properties show the geometry, label, ID etc, but a dialog
|
|
|
|
could just as easily show the user object of the cell. There might be a
|
|
|
|
reference to some process on the workflow engine as to how the inventory
|
|
|
|
is actually checked. This might be an application specific mechanism for
|
|
|
|
both the server and client to assign some identification to remote
|
|
|
|
method calls. Another value might be the type of object that process
|
|
|
|
returned, maybe a boolean or an integer to indicate stock level in this
|
|
|
|
case. Given that return type, it is possible to enforce constraints with
|
|
|
|
the diagram and provide visual alerts of if, say, the outgoing edges
|
|
|
|
decision check does not correspond to the return type of the vertex.</p>
|
|
|
|
|
|
|
|
<p>Next, as an example, the user objects of the outgoing edges might
|
|
|
|
contain a label and a boolean state. Again, the mxGraph-based editor
|
|
|
|
might provide the means to alter the boolean value. On the server, when
|
|
|
|
executing the process, it might follow the edges that correspond to the
|
|
|
|
boolean value returned by the decision node.</p>
|
|
|
|
|
|
|
|
<p>Keep in mind that the above example is very domain specific, it
|
|
|
|
is there to explain how the user object maps to the business logic of
|
|
|
|
the application. It visualizes how mxGraph creates what we term a <strong>contextual
|
|
|
|
graph</strong>. The context is formed by the connections between vertices and the
|
|
|
|
business logic stored within the user objects. A typical application
|
|
|
|
receives the visual and business logic from a sever, may allow editing
|
|
|
|
of both, then transmits both back to the server for persistence and/or
|
|
|
|
execution.</p>
|
|
|
|
|
|
|
|
<h4><a name="cell_types"></a>Cell Types</h4>
|
|
|
|
<p>As described previously, mxGraph is the primary API for using
|
|
|
|
this library and the same concept applies to cells. One basic state of
|
|
|
|
the cell not exposed on the graph is whether a cell is a vertex or an
|
|
|
|
edge, this call be performed on the cell or on the model.</p>
|
|
|
|
|
|
|
|
<p>There are two boolean flags on mxCell, vertex and edge, and the
|
|
|
|
helper methods set one of these to true when the cell is created.
|
|
|
|
isVertex(), isEdge() on mxIGraphModel are what the model uses to
|
|
|
|
determine a cell's type, there are not separate objects for either type.
|
|
|
|
Technically, it is possible to switch the type of a cell at runtime, but
|
|
|
|
take care to invalidate the cell state (see later section) after
|
|
|
|
changing the type. Also, be aware that the geometry object variable
|
|
|
|
means different things to vertices and edges. Generally, it is not
|
|
|
|
recommended to change a cell type at runtime.</p>
|
|
|
|
|
|
|
|
<h3><a name="group_structure"></a>Group Structure</h3>
|
|
|
|
<p>Grouping, within mxGraph, is the concept of logically associating
|
|
|
|
cells with one another. This is commonly referred to as the concept of
|
|
|
|
sub-graphs in many graph toolkits. Grouping involves one or more
|
|
|
|
vertices or edges becoming children of a parent vertex or edge (usually
|
|
|
|
a vertex) in the graph model data structure. Grouping allows mxGraph to
|
|
|
|
provide a number of useful features:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>Sub-graphs, the concept of a logically separate graph that is
|
|
|
|
displayed in the higher level graph as a cell per sub-graph.</li>
|
|
|
|
|
|
|
|
<li>Expanding and collapsing. Collapsing is the ability to replace
|
|
|
|
a collection of grouped cells visually with just their parent cell.
|
|
|
|
Expanding is the reverse of this. This behaviour can be seen by
|
|
|
|
clicking the small “-” in the top left corner of the group
|
|
|
|
cells of the swimlanes example in the <a
|
|
|
|
href="http://www.jgraph.com/demo/mxgraph/editors/workfloweditor.html">online
|
|
|
|
workfloweditor</a> example. This is described in the C<em>omplexity
|
|
|
|
Management</em> section below.</li>
|
|
|
|
|
|
|
|
<li>Layering. Layering is the concept of assigning cells to a
|
|
|
|
particular z-order layer within the graph display.</li>
|
|
|
|
|
|
|
|
<li>Drill down, step up. These concepts allow sub-graphs to be
|
|
|
|
visualized and edited as if they are a complete graph. In the <em>User
|
|
|
|
Objects</em> section we saw the “check inventory” vertex as a
|
|
|
|
single cell. Take, for example, the case where a developer is
|
|
|
|
describing each of the vertices in the process as the software
|
|
|
|
processes that perform the task. The application might have an option
|
|
|
|
to drill down into the check inventory vertex. This would result in a
|
|
|
|
new graph appearing that describes in detail how exactly the system
|
|
|
|
checks the inventory. The graph might have the title of the parent
|
|
|
|
“check inventory” vertex to indicate it is a child, as well
|
|
|
|
as the option to step-up back to the next level up.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>In grouping, cells are assigned a parent cell. In the simplest
|
|
|
|
case, all cells have the default parent as their parent. The default
|
|
|
|
parent is an invisible cell with the same bounds as the graph. This is
|
|
|
|
the cell returned by graph.getDefaultParent() in the helloworld example.
|
|
|
|
The x,y position of a vertex is its position relative to its parent, so
|
|
|
|
in the case of default grouping (all cells sharing the default parent)
|
|
|
|
the cell positioning is also the absolute co-ordinates on the graph
|
|
|
|
component. In the case all cells being added to the default root, the
|
|
|
|
group structure logically looks like, in the case of the helloworld
|
|
|
|
example, the diagram below.</p>
|
|
|
|
|
|
|
|
<p>Note the addition of the Layer 0 cell, this is the default
|
|
|
|
indirection in the group structure that allows layer changes with the
|
|
|
|
requirement of additional cells. We include it below for correctness,
|
|
|
|
but in later group diagrams it will be omitted.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><a name="ill_mx_man_hello_struct"><img src="images/mx_man_hello_struct.png"
|
|
|
|
WIDTH=441 HEIGHT=241 BORDER=0></a><br/>
|
|
|
|
<em>The group structure of the helloworld example</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>Also, note that the position of the edge label (x,y in geometry)
|
|
|
|
is relative to the parent cell.</p>
|
|
|
|
|
|
|
|
<p>If we go back to the simple workflow example in the User Objects
|
|
|
|
section, we can see what grouping might look like visually. In the
|
|
|
|
example the group cells represent people and the child vertices
|
|
|
|
represent tasks assigned to those people. In this example the logical
|
|
|
|
group structure looks like this:</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_log_group_struct.png"
|
|
|
|
name="ill_mx_man_log_group_struct"/><br/>
|
|
|
|
<em>The logical group structure of the workflow example</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>The workflow action vertices are the yellow children and the
|
|
|
|
swimlane group vertices are marked blue.</p>
|
|
|
|
|
|
|
|
<p>Inserting cells into the group structure is achieved using the
|
|
|
|
parent parameter of the insertVertex and insertEdge functions on the
|
|
|
|
mxGraph class. These functions set the parent cell on the child
|
|
|
|
accordingly and, importantly, informs the parent cell of its new child.</p>
|
|
|
|
|
|
|
|
<p>Altering the group structure is performed via the
|
|
|
|
mxGraph.groupCells() and mxGraph.ungroupCells() functions.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API functions:</strong></p>
|
|
|
|
|
|
|
|
<ul><li><strong>mxGraph.groupCells(group, border, cells)</strong> –
|
|
|
|
Adds the specified cells to the specified group, within a begin/end
|
|
|
|
update</li>
|
|
|
|
<li><strong>mxGraph.ungroupCells(cells)</strong> – Removes the
|
|
|
|
specified cells from their parent and adds them to their parent's
|
|
|
|
parent. Any group empty after the operation are deleted. The operation
|
|
|
|
occurs within a begin/end update.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<h3><a name="complexity_management"></a>Complexity Management</h3>
|
|
|
|
|
|
|
|
<p>There are two primary reasons to control the number of cells
|
|
|
|
displayed at any one time. The first is performance, drawing more and
|
|
|
|
more cells will reach performance usability limits at some point on any
|
|
|
|
platform. The second reason is ease of use, a human can only comprehend
|
|
|
|
a certain amount of information. All of the concepts associated with
|
|
|
|
grouping, listed above, can be used to reduce the complexity of
|
|
|
|
information on the screen for the user.</p>
|
|
|
|
|
|
|
|
<h4><a name="folding"></a>Folding</h4>
|
|
|
|
|
|
|
|
<p>Folding is the collective term we use for expanding and
|
|
|
|
collapsing groups. We say a cell is folded by making it's child vertices
|
|
|
|
invisible. There are a number of functions relating to this feature:</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API function:</strong></p>
|
|
|
|
|
|
|
|
<ul><li><strong>mxGraph.foldCells(collapse, recurse, cells)</strong>
|
|
|
|
– States the collapsed state of the specificed cells, within a
|
|
|
|
begin/end update.</li></ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p><strong>Folding related functions:</strong></p>
|
|
|
|
|
|
|
|
<p><strong>mxGraph.isCellFoldable(cell, collapse)</strong> –
|
|
|
|
By default true for cells with children.</p>
|
|
|
|
<p><strong>mxGraph.isCellCollapsed(cell)</strong> – Returns
|
|
|
|
the folded state of the cell</p>
|
|
|
|
|
|
|
|
<p>When a group cell is collapsed, three things occur by default:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>The children of that cell become invisible.</li>
|
|
|
|
<li>The group bounds of the group cell is used. Within mxGeometry
|
|
|
|
there is a alternativeBounds field and in groups cells, by default
|
|
|
|
store a separate bounds for their collapsed and expanded states. The
|
|
|
|
switch between these instances is invoked by mxGraph.swapBounds() and
|
|
|
|
this is handled for you within a foldCells() call. This allows
|
|
|
|
collapsed groups to be resized whilst when expanded again the size
|
|
|
|
looks correct using the pre-collapsed size.</li>
|
|
|
|
<li>Edge promotion occurs, by default. Edge promotion means
|
|
|
|
displaying edges that connect to children within the collapsed group
|
|
|
|
that also connect to cells outside of the collapsed group, by making
|
|
|
|
them appear to connect to the collapsed parent.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_expand_swim.png"
|
|
|
|
name="ill_mx_man_expand_swim"/><br/>
|
|
|
|
<em>Expanded swimlane</em></p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_collapse_swim.png"
|
|
|
|
name="ill_mx_man_collapse_swim"/><br/>
|
|
|
|
<em>Collapsed Swimlane</em></p>
|
|
|
|
|
|
|
|
<p>The above two images demonstrate these three concepts. In its
|
|
|
|
expanded state the upper group cell displays a small box in the top left
|
|
|
|
hand corner with a “-” character inside. This indicates that
|
|
|
|
clicking on this box collapses the group cell. Doing this we get the
|
|
|
|
bottom image where the group cell takes on its collapsed size. Child
|
|
|
|
vertices and edge that do not leave the group cell are made invisible.
|
|
|
|
Finally, edges that exit the group cell are promoted to appear to be
|
|
|
|
connected to the collapsed group cell. Clicking on the “+”
|
|
|
|
character that now appears within the box expands the group cell and
|
|
|
|
brings it back to its original state of the top image.</p>
|
|
|
|
|
|
|
|
<p>Using the mxGraph.foldCells() function, you can achieve the same
|
|
|
|
result programmatically as clicking on the expand/collapse symbols. One
|
|
|
|
common usage of this is when the application zooms out a specific
|
|
|
|
amount, clusters of cells are grouped and the grouped cell collapsed
|
|
|
|
(very often without the “-” box since the application is
|
|
|
|
controlling the folding). This way fewer, larger cells are visible to
|
|
|
|
the user, each one representing their children cells logically. You
|
|
|
|
might then provide a mechanism to zoom into a group, which expands it in
|
|
|
|
the process. You might also provide drill-down/step-up, explained next.</p>
|
|
|
|
|
|
|
|
<h4><a name="sub_graph_drilling"></a>Sub-Graphs, Drill-Down /
|
|
|
|
Step-Up</h4>
|
|
|
|
|
|
|
|
<p>Sometimes, as an alternative to expand/collapse, or possibly in
|
|
|
|
combination with it, your graph will be composed of a number of graphs,
|
|
|
|
nested into a hierarchy. Below we see a simple example:</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_drill_down.png"
|
|
|
|
name="ill_mx_man_drill_down"/><br/>
|
|
|
|
<em>An example top level workflow</em></p>
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<p>This simple workflow consists of three high level steps.
|
|
|
|
Obviously, the individual steps contain a number of sub-steps and we
|
|
|
|
will look at a sub-graph of the <em>Solve Bug</em> cell.</p>
|
|
|
|
|
|
|
|
<p>Under the <em>Solve Bug</em> vertex we have created a number of
|
|
|
|
children to represent the process of solving a bug in more detail, in
|
|
|
|
this case the process of solving a bug on the <a
|
|
|
|
href="http://en.wikipedia.org/wiki/Starship_Enterprise">Starship
|
|
|
|
Enterprise</a>.</p>
|
|
|
|
|
|
|
|
<p>In this example, which uses the GraphEditor example, the menu
|
|
|
|
option shown selected in the above image invokes
|
|
|
|
mxGraph.enterGroup(cell), which is one of the pair of core API functions
|
|
|
|
for sub-graphs.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API functions:</strong></p>
|
|
|
|
|
|
|
|
<ul><li><strong>mxGraph.enterGroup(cell)</strong> – Makes the
|
|
|
|
specified cell the new root of the display area.</li>
|
|
|
|
<li><strong>mxGraph.exitGroup()</strong> - Makes the parent of the
|
|
|
|
current root cell, if any, the new root cell.</li>
|
|
|
|
<li><strong>mxGraph.home()</strong> - Exits all groups, making the
|
|
|
|
default parent the root cell.</li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p>The root cell of the graph has been, up to now, the default
|
|
|
|
parent vertex to all first-level cells. Using these functions you can
|
|
|
|
make any group cell in the group structure the root cell, so that the
|
|
|
|
children of that parent appear in the display as the complete graph.</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_drilling.png" name="ill_mx_man_drilling"/><br/>
|
|
|
|
<em>Result of drilling down into the Solve Bug vertex</em></p>
|
|
|
|
|
|
|
|
<P>The same graph expanded using folding instead looks like:</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_top_level.png" name="ill_mx_mantop_level"
|
|
|
|
WIDTH=695 HEIGHT=227 BORDER=0></p>
|
|
|
|
<p>Exiting the group using the <em>shape->exit group</em> option,
|
|
|
|
which invokes mxGraph.exitGroup, brings you back to the original 3
|
|
|
|
vertex top level graph.</p>
|
|
|
|
|
|
|
|
<h4><a name="layer_filter"></a>Layering and Filtering</h4>
|
|
|
|
|
|
|
|
<p>In mxGraph, like many graphical applications, there is the
|
|
|
|
concept of z-order. That is, the order of objects as you look into the
|
|
|
|
screen direction. Objects can be behind or in front of other objects and
|
|
|
|
if they overlap and are opaque then the back-most object will be
|
|
|
|
partially or complete obscured. Look back to the <a href="#ill_mx_man_hello_struct">
|
|
|
|
graph structure of HelloWorld illustration</a> above. Children cells are stored under
|
|
|
|
parents in a deterministic order (by default the order in which you add
|
|
|
|
them).</p>
|
|
|
|
|
|
|
|
<p>If we move the cells in the HelloWorld example we see the
|
|
|
|
following result:</p>
|
|
|
|
|
|
|
|
<p><img src="images/mx_man_overlap.png" name="ill_mx_man_overlap"/><br/>
|
|
|
|
<em>Overlapped vertices</em></p>
|
|
|
|
|
|
|
|
<p>It can be seen that the <em>World</em> vertex is in front of the
|
|
|
|
<em>Hello</em> vertex. This is because the <em>World</em> vertex has a
|
|
|
|
higher child index than the <em>Hello</em> vertex, at positions 1 and 0
|
|
|
|
respectively in the ordered collection that holds the children of the
|
|
|
|
root cell.</p>
|
|
|
|
|
|
|
|
<p>To change order we use mxGraph.orderCells.</p>
|
|
|
|
|
|
|
|
<div id="coreapi">
|
|
|
|
<p><strong>Core API function:</strong></p>
|
|
|
|
|
|
|
|
<ul><li><strong>mxGraph.orderCells(back, cells)</strong> – Moves
|
|
|
|
the array of cells to the front or back of their siblings, depending on
|
|
|
|
the flag, within a begin/end update.</li></ul>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p>A sibling cell in mxGraph is any cell that shares the same
|
|
|
|
parent. So by invoking this on the <em>Hello</em> vertex it would then
|
|
|
|
overlap the <em>World</em> Vertex.</p>
|
|
|
|
|
|
|
|
<p>Ordering and grouping can be extended to form logically layered
|
|
|
|
groups. The cells are drawn via a depth-first search. Take the
|
|
|
|
HelloWorld example again and imagine that both the <em>Hello</em> and <em>World
|
|
|
|
</em>vertices have some hierarchy of children underneath them. The <em>Hello</em>
|
|
|
|
vertex and all of its children will be drawn before the <em>World</em>
|
|
|
|
vertex or any of its children. If <em>Hello</em> and <em>World</em> were
|
|
|
|
invisible group cells you then have two hierarchies of cells, one being
|
|
|
|
drawn entirely before the other. You can also switch the order of the
|
|
|
|
hierarchies by simply switching the order of the invisible group cells.</p>
|
|
|
|
|
|
|
|
<p>The concept of layering is demonstrated in the layers.html
|
|
|
|
example. Here buttons are used to set the visibility of group layer
|
|
|
|
cells. This example ties very closely into the concept of filtering.</p>
|
|
|
|
|
|
|
|
<p>In filtering cells with some particular attribute are displayed.
|
|
|
|
One option to provide filtering functionality is to check some state
|
|
|
|
before rendering the cells. Another method, if the filtering conditions
|
|
|
|
are simple and known in advance, is to assign filterable cells by
|
|
|
|
groups. Making the groups visible and invisible performs this filtering
|
|
|
|
operation.</p>
|
|
|
|
|
|
|
|
<br/>
|
|
|
|
|
|
|
|
<hr size="1">
|
2014-10-03 12:49:36 +00:00
|
|
|
© 2006-2014 by JGraph Ltd.
|
2012-05-21 20:32:26 +00:00
|
|
|
</body>
|
|
|
|
</html>
|