This document explains how to use yFiles AJAX for integrating the sophisticated yFiles for Java graph visualization framework into state of the art web applications. yFiles AJAX is a product of yWorks GmbH, creator of yFiles for Java and other fine products.
Please see the bundled license file for license terms.
This product contains software developed by the Dojo Foundation (http://dojofoundation.org/) distributed under the terms of the Academic Free License v2.1.
This product contains software developed by the Apache Software Foundation (http://www.apache.org/) distributed under the terms of the Apache License, Version 2.0.
This product contains Nuvola icons developed by David Vignoni (http://icon-king.com/) distributed under the terms of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1.
This product contains software developed by Jason Hunter and Brett McLaughlin (http://www.jdom.org/) distributed under the terms of this license.
Web applications are client/server applications consisting of a standard web browser for the client side which is served by a dedicated server component over a network like the internet or an intranet. Web applications have become more and more popular, since deployment, updates and maintenance are much easier than for desktop applications.
AJAX enables web applications that feel similar to desktop applications. This is achieved by dynamically exchanging parts of the displayed web page instead of (re-)loading web pages as a result of user interactions.
On the downside, more effort needs to be spent for creating a suitable client using only a standard web browser and JavaScript compared to a desktop application. Moreover, the underlying technology for dynamically changing the appearance of a displayed web page is not (yet?) fully standardized across different browsers. There are different frameworks available which ease the development of AJAX applications by dealing with browser differences and providing components which provide a higher level of functionality.
yFiles AJAX provides a basis for web applications that need to visualize and edit graphs, diagrams or networks. It consists of client and server side components. The server side is based on the successful yFiles for Java library. The client side is realized in JavaScript. It is based on the Dojo toolkit and uses the AJAX approach.
From a high-level perspective yFiles AJAX can be described as follows.
yFiles AJAX ships with demo applications illustrating how to use it and how to add application specific functionality.
src of the deployed yFiles AJAX web application.
Examples and javascript/demos of the deployed
yFiles AJAX web application. Note that the sources are not available
online, i.e. you cannot get them from live.yworks.com.
webapp/yfiles-ajax.war file in the distribution using an archive
program or by using ant unzip-war in the main directory of the distribution.
There are three tutorials for using and extending
yFiles AJAX in this document.
The following is a simplified overview of the logical components of yFiles AJAX.

The client side of yFiles AJAX is based on the Dojo toolkit. The client side components can be grouped with respect to their roles with respect to the Model View Controller Pattern (MVC), since the architecture is similar to the yFiles for Java y.view package.

onNodeCreated or onEdgeCreationFailed
which allow listeners to react on changes in the graph.
HitTest gets its data for answering queries from the TileServlet. The hit tests
themselves are performed on the client side.
isGroupNode or getParent) of the graph (grouping and folding of nodes as in
the yFiles for Java library on the server). It also lets you update the
nested structure with functions like createGroup, moveToSubgraph or
closeGroup. So far it is a proxy for the y.view.hierarchy.HierarchyManager
on the server. Additionally, the client side hierarchy manager also lets you specify which subgraph in the
hierarchy of nested graphs you want to display (switchToSubgraph, switchToParent).
There are events like onCreateGroup and onSwitchToSubgraphFailed.

GraphCanvas can be used for an overview in conjunction with
the
ViewPortMarkerViewPortMarker marks the visible region
of the main GraphCanvas in the overview GraphCanvas and allows
the user to change it.
GraphCanvas. This can be used
to implement a "Zoom Area" feature for example.

The controller part in the MVC pattern varies the most depending on the specific application. yFiles AJAX provides the building blocks for a specific controller with the basic InputMode class, some specific "one-shot" input modes which get activated for a narrow task (like creating an edge or zooming to an area of interest) and immediately finish after the task has been done. There is a main input mode which handles some input directly and dispatches other input to specialized input handlers.
With version 1.2 of yFiles AJAX a new framework for adding custom server side actions has been introduced. It also contains a client side part, the ServerAction class, which wraps a call to a custom server side action.
CreateEdgeMode. An InputMode is initialized for a specific
GraphCanvas.InputModes have a set of event handlers which are attached, if the InputMode
is activated (activate()). The event handlers are detached, if the InputMode
is deactivated (deactivate()).InputModes can be chained using the setChild() function. If this is invoked
on an active parent input mode with a child input mode as its argument, then the parent input mode
passes the control to the child by detaching its event handlers and activateing the child.
The parent input gets reactivated once the child is deactivated.
Rubberband to display the region to zoom to.
yfiles.client.tiles.ZoomAreaMode
except for its result. The selection made by the user is applied to a GraphSelection
instance supplied to the initializer. This input mode can optionally be made aware of the nesting structure
of the graph it acts upon by passing the hierarchy manager for the graph to its constructor. In this case
group nodes are only selected, if their bounds are totally inside the selection area instead of just
having an overlap. This allows selections inside a group node without selecting the group node itself.
GraphSelection.
At activation time, it checks whether the selection
currently contains at least one node. For all selected nodes, it displays movable ghost objects.
It is assumed that the user pressed the left mouse button at activation time. If the user moves
the mouse, the ghosts are moved accordingly. If the user releases the left mouse button, the selected
nodes are moved to the current ghost positions. Then the mode deactivates itself. This input mode can also
optionally be made aware of the nesting structure of the graph. In this case it handles moving the selection
to a different level in the nesting structure, if the SHIFT key is pressed when the selection is dropped.
yfiles.client.tiles.widget.CanvasDragLine. If the user releases the left mouse button,
it is checked whether there is an end node for the edge at the current mouse position. If this is the
case, then a new edge is created. Finally, the mode deactivates itself.MoveSelectionMode
is activated, if the user starts dragging with the mouse positioned over a selected node. Additionally,
further user gestures are handled without using extra input modes, for example creating a node, if the user
clicks on an empty space and there is no current selection. The edit mode can optionally be made aware of the
nesting structure of the graph. In this case it initializes its child rectangular selection and move selection
modes to be aware of the nesting structure. Moreover, it only activates the create edge mode for group nodes,
if the user starts dragging the mouse at the border of the group node. On mouse drags inside a group node the
edit mode activates the rectangular selection mode. The edit mode also handles clicks on the state label of
group nodes (e.g. opening a closed group (aka folder) node on clicking on its plus sign).
demos.widget.GraphEditor is a demo application for editing graphs realized as a single
Dojo widget. It combines most of yFiles AJAX features with a GUI with a toolbar, a context menu and
floating tool windows. It has an online help page which describes its usage. The source is available
in the javascript/demos/widget directory. Note that the
sources are not available online, i.e. you cannot get them from live.yworks.com.

yFiles AJAX uses standard servlet technology for the server side. It provides the following servlets.
ActionHandler when it is called. The
ActionContext provides the client side context to the server side action.
ActionHandler when it is called. The
ClientControl provides control on the post processing on the client side after
the server side action has been performed.
All files needed for the tutorials are contained in the web application archive yfiles-ajax.war
which ships with yFiles AJAX. You can extract those files from the archive with an archiver, which can handle
the ZIP format. Alternatively, you can let Ant do the job for you, which is described in the
following. Ant can be obtained from here.
ant tutorials
tutorials which contains all necessary
files for the tutorials.
Using yFiles AJAX means writing a web application using yFiles AJAX servlets on the server side and yFiles AJAX JavaScript classes on the client side. The action framework introduced in yFiles AJAX 1.2 simplifies adding server side functionality. The next tutorial provides details on using the action framework. The third tutorial describes how to use a custom servlet for extending the server side. In this tutorial we start by just using the existing components for the client and the server side.
Information on writing web applications in general can be found in this tutorial. General information on using Dojo can be found in the documentation section of the Dojo website.
The source code for the demos which ship with yFiles AJAX is included (the HTML files reside in the
top level directory and the "Examples" subdirectory of the deployed yFiles AJAX web application,
the JavaScript source files can be found in the "javascript/demos" subdirectory). Note that the
sources are not available online, i.e. you cannot get them from live.yworks.com. The demo
source code demonstrates some of the possibilities of yFiles AJAX. In the following, we describe how to use
yFiles AJAX and how to extend it using simpler examples which are derived step by step in order
to explain the basics.
The following describes the steps to set up a basic web application using yFiles AJAX as a tutorial. We want to achieve this result (opens in another window or tab, note that this only works, if you opened the yFiles AJAX Developer's Guide from a deployed yFiles AJAX web application).
GraphCanvas displaying a fixed graph.
We assume some basic knowledge on writing web applications. Modern IDEs like Eclipse or IDEA provide useful tools for doing this.
WEB-INF/lib
of the deployed yFiles AJAX web application or in tutorials/WEB-INF/lib, if you followed the
instructions for extracting the tutorial files), and your yFiles for
Java jar file
y.jar to the libraries to be deployed, such that they end up in the WEB-INF/lib
directory of your new web application.
yfiles-ajax-license.xml (either the evaluation license file, which can be
found in the WEB-INF directory of the yFiles AJAX web application for the evaluation version
or your proper license file) to the WEB-INF directory of your new web application.
WEB-INF/web.xml file of your web application should at least contain
the mappings for the LoaderServlet and the TileServlet of yFiles AJAX
like in this template.
javascript/dojo, javascript/dijit and javascript/dojox.
resources/graphs as a deployed subdirectory. This
directory is used for loading graphs from files on the server side. Currently,
the name is fixed.
Create a new HTML page in the main directory of your web application. There is some basic JavaScript code which needs to be loaded into an HTML page in order to use Dojo with it. Add the following to the head of your HTML page.
<script type="text/javascript" src="javascript/dojo/dojo.js" djConfig="parseOnLoad: true"></script>The
src attribute describes the path to the basic Dojo Javascript file
in the directory structure as described in the last step. If you move your HTML page
to another directory, the path has to be adapted.
The core Dojo code loaded in Step 2 contains the Dojo package system which
provides the dojo.require() function for loading Dojo sources.
Now we add the layers (Dojo term for packaged JavaScript sources, more information can be
found in this section), which contain the yFiles AJAX client side components.
Therefore we load two additional JavaScript files by adding the following lines below the line for
adding Dojo itself.
<script type="text/javascript" src="javascript/dojo/yfiles-ajax-prerequisites.js"></script> <script type="text/javascript" src="javascript/dojo/yfiles-ajax-base.js"></script>The
GraphCanvas uses the Dojo packaging system, but it does not belong
to the dojo namespace. We have to register the yfiles namespace to
which GraphCanvas belongs with a call to registerModulePath. This is done
by adding the following lines to the head of the page after the lines just added.
<script type="text/javascript">
dojo.registerModulePath("yfiles", "../yfiles");
dojo.require("yfiles.client.tiles.widget.GraphCanvas");
</script>
The source code for yFiles AJAX widgets and classes is not shipped,
thus there is no javascript/yfiles directory. The yFiles
AJAX widgets are provided by the layer files we included above.
The path used in dojo.registerModulePath is relative to the location of
the dojo.js file loaded in Step 2. It does not depend on the location of
the HTML page.
Now you can add the GraphCanvas to the body of the page. The widget
uses the space provided by its parent element. In this case we use a div
with 400 pixels width and height as the frame for the graph canvas.
<div style="width: 400px; height: 400px; border: solid blue;"> <div dojoType="yfiles.client.tiles.widget.GraphCanvas" id="canvas" path="computers.ygf"></div> </div>The
id attribute of the GraphCanvas is needed to
identify the widget in custom JavaScript code. This will be used in the next
step of this tutorial. The path attribute tells the canvas which
graph to display. It is not mandatory, because there is also a function for
setting the graph to be displayed any time after the widget was created.
Zooming with the mouse wheel and panning are default features of the graph canvas, thus there is no need for configuration or additional code to handle that. In order to demonstrate how to talk to the graph canvas using custom JavaScript code we add two zoom buttons to the page.
<div>
<button onclick="dijit.byId('canvas').setZoom(2.0 * dijit.byId('canvas').zoom);">
Zoom In
</button>
<button onclick="dijit.byId('canvas').setZoom(0.5 * dijit.byId('canvas').zoom);">
Zoom Out
</button>
</div>
You can get a reference to a specific Dojo widget with a known id by using
dijit.byId(). The graph canvas has a readonly attribute zoom
holding the current zoom factor and a function setZoom() for setting
a new zoom factor. We use the onclick event handlers of the buttons
to increase or decrease the zoom factor which results in zooming in or zooming
out, respectively.
This concludes the tutorial. The complete source code of the HTML page can be viewed by using the
view source feature of your browser for
this page. The file is also available at
tutorials/Examples/basic.html, if you extracted the tutorial files as described
above.
NOTE: The graph canvas has an additional parameter baseURL=".." in the
HTML page for this tutorial extracted from the distribution as described above.
The baseURL attribute is needed, if the HTML page does not reside in the main
directory of the web application, because the server requests from the graph canvas always
use relative URLs. The example resides in the subdirectory Examples. Thus the
baseURL attribute has the value "..". Moreover, the
paths for including the dojo.js file and the Javascript files for yFiles AJAX
in the header are adapted.
You can extend yFiles AJAX both on the client and on the server side. On the client side,
you can for example add new widgets which react to events provided by existing yFiles AJAX widgets.
An example for this is the ViewPortMarker widget, which adds new functionality
on the basis of two GraphCanvas instances.
Another example for a client side extension is the GraphInfo widget
which displays information on the graph as a whole or on parts of it like a single
node. It relies on information provided from the server side. This information
is produced by the
InfoServlet,
which is an example of a server side extension. Using a custom servlet is part of the next tutorial.
In this tutorial we create a simple game, Treasure Hunt. A graph is displayed and a treasure is hidden at one of its nodes. If the player clicks a node, it will either be the right one with the treasure or it is another node without the treasure. If there is no treasure, the player gets a hint that the treasure is for example two nodes away.
There are of course several ways to implement this game. Just selecting a random node at the beginning and then checking whether it has been clicked can be done without any server call. Computing the distance to the node with the treasure would be rather complicated, since the graph structure (what are the neighbors of a node?) is not present at the client side.
yFiles for Java, which is available at the server side, does have access to the graph structure. Moreover, it offers an algorithm for computing the distance from one node to every other node in the graph. Let's just use that. We could wrap the call to the algorithm with a custom servlet. The next tutorial describes the approach of creating a custom servlet and calling it from the client side.
In this tutorial we'll use the action framework instead of writing a custom servlet. The action framework was introduced in yFiles AJAX 1.2. It simplifies adding custom server side behavior triggered by the client side to a web application with yFiles AJAX.
NOTE: This tutorial is based on the last tutorial. We assume that the HTML page is located in the main directory of the web application as in the last tutorial. If this is not the case some paths need to be adjusted.
We want to display a graph and thus use a GraphCanvas as in the previous
tutorial. We need a way to let the player pick a node. The graph canvas has some
functions for mouse events related to nodes. They are called, if we tell the canvas that
we are interested in node events. This can be done in the HTML markup of the canvas. We'll
use a different graph this time and a larger canvas. Since we want to perform some code
after the graph has been loaded (computing the distances for the first time), we do not
specify the graph in the markup for the canvas, but set the path for the graph in Javascript code.
In the body of the page we use the adapted canvas mentioned above and
a placeholder for displaying hints for the player, an initially empty paragraph
with the id hint.
<body> <h1>Treasure Hunt</h1> <p> There is a treasure hidden at one of the nodes! </p> <div style="width: 600px; height: 500px; border: solid blue;"> <div dojoType="yfiles.client.tiles.widget.GraphCanvas" id="canvas" nodeEvents="true"></div> </div> <p id="hint"></p> </body>
We also change the title of the page by replacing the previous title line in the head of the page with the following one.
<title>Treasure Hunt</title>
The action framework contains one class for the client side:
ServerAction
.
An instance of ServerAction wraps the call to the server triggering a server side
action. It sends some information about the client state to the server and takes care of the
server response. This means that you do not have to create a new protocol to talk to your
server side code. In order to use a ServerAction instance, we have to require the
corresponding class. Add the following line in the header after the require call for the
GraphCanvas class.
dojo.require("yfiles.client.tiles.ServerAction");
Initially and every time the player has found the treasure we hide a new treasure
at a random node and compute all the distances from all nodes to the node with the treasure
on the server side. If the player clicks a node, we use the distance information to
decide whether the treasure was found or to display a hint with the distance to the
treasure. The client side of the action for hiding the treasure, the
hideTreasureAction, is created as follows in a new Javascript block in
the head of the page after the block with the require calls.
<script type="text/javascript">
var distances;
var hideTreasureAction = new yfiles.client.tiles.ServerAction({
id : 'yworks.demos.actions.hideTreasure',
graphName : 'treasure-islands.graphml',
postRun : function() {
distances = dojo.fromJson(this.getCustomResponse());
}
});
</script>
The handler for the server side action is identified by the id
yworks.demos.actions.hideTreasure. We tell the server side which graph to use
by specifying the symbolic name of the graph. The graph file treasure-islands.graphml
has to be added to the resources/graphs directory.
The function with the postRun key in the parameter object
given to the ServerAction constructor is called whenever a response from
the server arrives (and no error occurred). The function is called without any parameters,
but it is called in the scope of the calling ServerAction instance, so we can use this
inside the postRun function to access the calling action. The postRun
function of the hideTreasureAction uses the access to the calling action for
getting the response from the server side code: this.getCustomResponse(). The
custom response from the server, which is always a string, is expected to be in JSON format
and a JavaScript object distances is constructed from it.
The canvas has the following functions dealing with node events. Since we enabled node events in Step 1, these functions will be called with the id of the node as the argument, if the corresponding events happen.
onNodeClicked is called when a node is clickedonMouseOverNode is called when the mouse enters a nodeonMouseOutNode is called when the mouse leaves a node
In order to run the hide treasure action initially and to set up the event handling,
we use a function init, which should be executed once after the page is loaded
and the canvas is constructed. In the init function we first set the path to
the graph. This triggers loading the graph on the server. When the graph is loaded, we run
the hide treasure action for the first time and connect the onClickNode and
onMouseOutNode events of the graph canvas. Add the following functions
to the Javasript block in the head of the page which already contains the
hideTreasureAction variable.
function init() {
canvas = dijit.byId('canvas');
hint = dojo.byId('hint');
dojo.connect(canvas, 'pathSet', window, 'onPathSet');
canvas.setPath('treasure-islands.graphml');
}
function onPathSet() {
hideTreasureAction.run();
dojo.connect(canvas, 'onClickNode', window, 'feedback');
dojo.connect(canvas, 'onMouseOutNode', window, function() { hint.innerHTML = ''; } );
}
The effect of a call like dojo.connect(canvas, 'onClickNode', window, 'feedback');
is that each time, when the onClickNode function of the canvas is called, the
feedback function of the window (which means the global feedback
function) gets called immediately afterwards with the same parameters. We'll define the
feedback function in the next step. The parameter of the onClickNode function
of the canvas is the id of the node which was clicked. We could also interpret the mouse enter
event as searching for the treasure, but that would probably lead to too much accidental searching.
We use the onMouseOut event to remove the hint, since if there really was a hint,
then the mouse just left the node for which the hint was computed.
In order to run the init function initially we use dojo.addOnLoad.
Insert the following Javascript block just before the end of the body of the page.
<script type="text/javascript"> // Call init after page load. dojo.addOnLoad(init); </script>
For providing the feedback to the player we use the feedback function in the
Javascript block in the header.
function feedback(nodeId) {
if(!distances) {
return;
}
var distance = distances[nodeId];
if(distance == 0) {
// Hide another treasure.
distances = null;
hideTreasureAction.run();
// Congratulations!
// <Insert your favorite effect here.>
alert('Congratulations! You found the treasure!\n\nThere is yet another treasure...');
} else {
// Display hint.
var distStr = distance == 1 ? "one node" : distance + " nodes";
hint.innerHTML = 'No, there is no treasure here, but it is only ' +
distStr + ' away. Keep on searching!';
}
}
We get the distance from the node where the player is searching to the treasure from
the distances object. We assume that it looks like the following JavaScript
object (we'll take care of that assumption on the server side).
{
"n-0" : 1,
"n-1" : 0,
"n-2" : 1,
"n-3" : 2
}
For each member, the key is the id of a node of the graph and the value is the length of the
shortest path from this node to the treasure or in other words the distance to the treasure.
If the distance is 0, the player found the treasure, congratulations and the game starts
again. Otherwise we tell the player the current distance to the treasure by populating the
hint placeholder in the page. The complete client side page with the necessary
dojo.require calls added looks like this
(use the view source feature of your browser).
NOTE: The complete tutorial HTML page is located in the subdirectory Examples
in the yFiles AJAX distribution. Therefore, some paths have to be adjusted. This is relevant for
including the Javascript files for Dojo and yFiles AJAX in the header and for the calls to the server
side made by the canvas and the server action instance. The canvas has a baseURL attribute
for this purpose, which was already mentioned in the last tutorial. The server action has an optional
parameter url which specifies the relative URL of the generic ActionServlet
on the server which takes care of dispatching requests made by ServerAction
instances on the client.
As already mentioned you do not have to write your own servlet, if you use the action
framework. You can write an action handler instead which implements the
ActionHandler
interface. There is just one method to be implemented in the action handler interface:
handleAction. It takes two parameters. The first parameter, an ActionContext
instance, describes the client side environment for the action (e.g. the graph to be considered). The
second parameter, a ClientControl instance, allows to control the client side post-processing.
The client control also offers a method for setting the custom response.
Create a new class implementing the ActionHandler interface, e.g.
tutorials.HideTreasureAction.
package tutorials;
import com.yworks.yfiles.server.tiles.servlet.action.ActionHandler;
import com.yworks.yfiles.server.tiles.servlet.action.ActionContext;
import com.yworks.yfiles.server.tiles.servlet.action.ClientControl;
public class HideTreasureAction implements ActionHandler {
public void handleAction(ActionContext context, ClientControl control) {
}
}
In the implementation of the handleAction method for the hide treasure action,
we first find out for which graph to hide a treasure. The action context provides the actual
graph instance for the symbolic graph name sent from the client.
public void handleAction(ActionContext context, ClientControl control) {
// Get the graph specified by the client request.
Graph2D graph = context.getGraph();
Note that the graph could be null
depending on the parameters of the client side ServerAction instance,
but for the hide treasure action this should not happen.
The next step is to select a node for hiding the treasure.
// Select a treasure node.
Node treasureNode = chooseTreasureNode(graph);
Then we compute the distances to the treasure node by means of an algorithm
provided by the y.algo.ShortestPaths class.
// Compute the distances.
double[] distances = new double[graph.N()];
ShortestPaths.uniform(graph, treasureNode, false, distances);
Finally, we return the distances as a JSON string.
// Send the distances to the client.
control.setCustomResponse(createJSONDistancesString(graph, distances));
}
Choosing a random node in the graph can be done by using a yFiles for Java node cursor
and a random position in a separate private helper method of the
HideTreasureAction.
private Node chooseTreasureNode(Graph2D graph) {
// Hide the treasure at a random node.
Random random = new Random();
int nodeCount = graph.N();
int position = random.nextInt(nodeCount);
int count = 0;
for (NodeCursor nodeCursor = graph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
if (count++ == position) {
return nodeCursor.node();
}
}
return null;
}
For creating the JSON string containing the distances from the treasure node to the
other nodes we use the
JSONStringBuilder
private String createJSONDistancesString(Graph2D graph, double[] distances) {
// Create a string in JSON format containing the distances to the treasure node.
JSONStringBuilder builder = new JSONStringBuilder();
for (NodeCursor nodeCursor = graph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
Node node = nodeCursor.node();
builder.addMember(BaseServlet.getId(graph, node), (int) distances[node.index()]);
}
return builder.getJSONString();
}
Note that the index of a node is not an id, if the graph is allowed to change. The
index is unique, but it changes, if the graph changes. In the treasure hunt game the graph
does not change, but since yFiles AJAX also allows changing the graph, the index
cannot be used as an id for a node. yFiles AJAX uses ids which can be retrieved
by using public static methods of the BaseServlet.
Requests from client side ServerAction instances are handled by
by the generic ActionServlet which is part of yFiles AJAX. It uses the id
(e.g. yworks.demos.actions.hideTreasure), which is part of the request, to look up the
right action handler. The action handler is registered with the ActionServlet
by means of an initialization parameter in the web.xml file for the
application. Add an entry for the ActionServlet and a corresponding servlet mapping
to your web.xml file, if they are not already there (note that the entries in the
web.xml file have to be ordered according to their types, e.g. mappings need to be
declared after all servlet entries).
<servlet>
<servlet-name>ActionServlet</servlet-name>
<display-name>Action Servlet</display-name>
<description>handles custom actions</description>
<servlet-class>com.yworks.yfiles.server.tiles.servlet.action.ActionServlet</servlet-class>
<init-param>
<param-name>yworks.demos.actions.hideTreasure</param-name>
<param-value>tutorials.HideTreasureAction</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ActionServlet</servlet-name>
<url-pattern>/yFilesAction</url-pattern>
</servlet-mapping>
The name of the parameter is the id for the action (yworks.demos.actions.hideTreasure)
and the value is the fully qualified class name of the class implementing the server side of
the action (tutorials.HideTreasureAction). The name of the request is
yFilesAction by default, but it can be configured in the client side
ServerAction class and the web.xml file.
This concludes the second tutorial. The complete source code for the action handler
can be found in the src folder of the yFiles AJAX web example application or
in the src subdirectory of the tutorials directory, if
you extracted it from the web archive as described above.
However, the HideTreasureAction is part of the
com.yworks.yfiles.server.tiles.demos package in these sources.
More information on the action framework is available in this section. The Swim Lanes demo application also uses the action framework.
In this tutorial we want to extend the basic example developed in the first tutorial in order to be able to collapse and expand subtrees of a rooted tree, if the user clicks a node label showing either a + or a - sign depending on the collapsed/expanded state of the subtree rooted at that node. The graph resulting from an expand or collapse operation should be redrawn to display the additional nodes after an expand operation and to show a more compact drawing after a collapse operation, respectively. Initially, a graph should be displayed, which hides most of the nodes.
This time we want to have a different layout. The graph canvas should use the whole page and adapt itself to page resizes.
From a high level perspective we have the following new requirements.
Extending the server side typically means adding new servlets and servlet mappings to the web application. In this case we add a TreeCollapserServlet to the server side.
Since this is not a tutorial on yFiles for Java, we will not go into all the details of the new servlet (the source code is commented, too), but just mention some important points.
TreeCollapserServlet inherits from BaseServlet.
resources/graphs for the
graph to be displayed, but create an initial graph programmatically and cache it
using the fixed name "CollapsibleTree" as a reaction to the "initialize" request.
The method cacheGraph() is inherited from BaseServlet.
Similarly, it is possible to get a graph to be displayed from other sources, e.g.,
from a data base.
Add the servlet and mappings for "initialize" and "toggleNode" to the web deployment descriptor.
... <servlet> <servlet-name>TreeCollapserServlet</servlet-name> <display-name>Tree Collapser Servlet</display-name> <description>collapses and expands subtress of a tree</description> <servlet-class>com.yworks.yfiles.server.tiles.demos.TreeCollapserServlet</servlet-class> </servlet> ... <servlet-mapping> <servlet-name>TreeCollapserServlet</servlet-name> <url-pattern>/TreeCollapser/toggleNode</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>TreeCollapserServlet</servlet-name> <url-pattern>/TreeCollapser/initialize</url-pattern> </servlet-mapping> ...
On the client side, it is possible to react on graph events by connecting to the interesting
graph events fired by the graph canvas like onClickNodeLabel. Have a look at the
TutorialGraphListener.
It uses the Dojo packaging system, such that it can be included into
an HTML page using dojo.require(). Copy the file TutorialGraphListener.js
to a subdirectory examples of the javascript directory of your web application.
Using dojo.registerModulePath you can tell Dojo that there is a new package to consider for
serving dojo.require calls. The details are given in the next step.
The TutorialGraphListener is defined using dojo.declare().
This a convenience function for defining classes in Dojo. The constructor
for a new instance is the constructor function. The TutorialGraphListener
caches the canvas and calls _initializeGraph() in order to set up the initial graph.
As a third step it connects the onClickNodeLabel of the canvas with its own
onClickNodeLabel function. After doing so, the onClickNodeLabel function of the
TutorialGraphListener will be called once after each call to onClickNodeLabel
on the canvas with the same arguments. The first argument given to onClickNodeLabel
is the id of the clicked node label.
In _initializeGraph() an "initialize" request is sent to the servlet
defined in step 1. Additionally, the canvas is set to the graph created as a result
of the "initialize" request. The second step depends on the first one. It can only
succeed, if the graph is already cached. Note that dojo.xhrPost() is
asynchronous by default. Calling setPath() as a separate statement after
the dojo.xhrPost() call would thus fail sometimes. dojo.xhrPost()
can be made synchronous, but that locks the browser GUI and thus is not advisable.
If the server request initiated by dojo.xhrPost() succeeds, Dojo calls
the "load" function from the anonymous parameter object supplied to the call. Using the
load function is a nice possibility to synchronize code depending on the outcome
of a former server call without using synchronous server calls.
We add our custom click behavior in the onClickNodeLabel() function
of the TutorialGraphListener. If the user clicks a node label, we send
a request to the new servlet, "toggleNode" in this case, and refresh the canvas once
the server side operation has succeeded.
The response for the "toggleNode" request is an object encoded with JSON (JavaScript Object Notation) additionally embedded surrounded by a comment. Dojo supports this encoding and returns the evaluated string as a JavaScript object to the load function as the first parameter. The JSON object is surrounded by a comment for security reasons.
The response of the "toggleNode" is an object with two attributes, bounds
and shift. bounds contains the new graph bounds after the toggle
node operation and shift describes the displacement of the given node as a
result of the server side operation (which includes redrawing the tree). There is a
refresh function on the graph canvas which can be supplied with the bounds
and the shift, such that the graph display is refreshed and the node which was
clicked by the user remains at the same position. This helps the user in visually understanding
the difference resulting from the "toggleNode" operation.
As a final step we have to adapt the HTML page from the previous tutorial, such that the graph listener from step 2 is used. Copy your previous HTML file and remove everything in the body (between <body> and </body>). First, we change the requires section in the head of the page as follows.
<script type="text/javascript">
dojo.registerModulePath("yfiles", "../yfiles");
dojo.require("yfiles.client.tiles.widget.GraphCanvas");
dojo.registerModulePath("examples", "../examples");
dojo.require("examples.TutorialGraphListener");
</script>
Now we want to use the listener. We cannot create the listener
in a script section in the head, because it depends on the
canvas which is probably not yet constructed. We create the listener
on page load using dojo.addOnLoad(). This way, we can be
sure that the canvas widget is already constructed. Therefore, we add
a JavaScript section to the end of the body of the page which creates
an instance of the listener.
<script type="text/javascript">
dojo.addOnLoad(function() {
var canvas = dijit.byId('canvas');
new examples.TutorialGraphListener(canvas);
});
</script>
Next we change the canvas such that it no longer loads the graph from
the previous tutorial by removing the path attribute.
Additionally, we enable reporting of node label events by setting
nodeLabelEvents to true.
<div dojoType="yfiles.client.tiles.widget.GraphCanvas" id="canvas" nodeLabelEvents="true"></div>
Disabling scroll bars and using the whole visible area can be achieved by
removing the div enclosing the graph canvas and adding
the following style section to the head of the HTML page.
<style type="text/css">
html, body, #canvas {
width: 100%; /* fill the visible area */
height: 100%;
overflow: hidden; /* erase scrollbars */
padding: 0 0 0 0;
margin: 0 0 0 0;
}
</style>
That's it! The complete source code of the HTML page can be viewed by using the view source feature of your browser for this page. Note that the listener is included directly from its
In order to wire GUI events to application specific functionality, you have to add some
controller code. In the first tutorial for example, if the user presses the
"Zoom In" button, we increased the zoom factor of a GraphCanvas
widget.
The tutorial uses the easy solution to just call the desired function
setZoom() directly from the HTML markup of the event source, the button
in the example. This may compromise the readability and maintainability of
the HTML code for larger applications, while it is certainly ok for small
applications like the tutorial.
You can extract the code from the onclick attribute into a global
JavaScript function (e.g., zoomIn()) defined in the header of the HTML
page or in an external JavaScript file loaded in the header. This shortens the value
of the onclick attribute to just the call of that function. Moreover,
you can call this function from other places like a menu entry as well.
With Dojo it is also possible to use the Dojo event system to connect an event to calling a function on another object without adding an event handler attribute directly in the HTML code. The following is an example from the GraphViewer demo.
dojo.connect(dojo.byId('graphMenu'), 'onchange', window, 'graphSelected');
This connects a standard select element with id "graphMenu"
to a global JavaScript function graphSelected(). Note that the
elements to be connected have to exist already at the time of execution of
dojo.connect(), thus code like this is typically invoked
from a function called on load of the HTML page using dojo.addOnLoad(),
since the select element might not yet exist when JavaScript code
in the head of a page is executed.
In the demos which ship with yFiles AJAX there is an explicit controller object, an
instance of a JavaScript class GraphClient.
The GraphClient class has a function zoomIn() which
can be called from any event source, once the GraphClient instance
is initialized.
Although the controller code is highly dependent on the specific application,
the GraphClient class tries to be generic. It assumes that there is
a main GraphCanvas and optionally a RubberBand for the
main GraphCanvas, a second GraphCanvas serving as an
overview and a GraphInfo widget (part of the demos). If any of the
optional widgets is not there, the corresponding functionality is simply not
initialized or executed. The GraphClient
code ships with
yFiles AJAX, so you can adapt it to the needs of your application. Note that
the sources are not available online, i.e. you cannot get them from
live.yworks.com.
The GraphClient is initialized and assigned to a
global variable in a function called on load of the HTML page (using
dojo.addOnLoad()). This is important, since the widgets may not yet
exist, if the client is initialized directly from the head of the HTML page.
If you want to dynamically change the controller code, which is a natural requirement
in more complex application like a graph editor, you can also use the infrastructure
provided by the yfiles.client.tiles.InputMode and its subclasses.
An example for using input modes is the Graph Editor demo.
yFiles AJAX ships with five demo applications, a Graph Viewer, a Swim Lanes, a Grouped Graph, a Graph Editor and a Collapsible Tree demo application.
Like the tutorials the demo applications also shed some light on using and extending
yFiles AJAX. The Graph Viewer demo application adds
a new widget called GraphInfo for displaying additional information
on certain aspects of a graph like the graph as a whole or a specific node. This
widget is used "statically" as part of the initial GUI and dynamically
for displaying tooltips for the nodes of the graph. There is a corresponding
servlet, the
InfoServlet,
for providing the information to be displayed by the GraphInfo
from the server side. In addition, the Graph Viewer demo shows how to set up an
overview canvas.
The Swim Lanes demo application uses two features introduced with yFiles AJAX 1.2: configuration of the server side views used for generating the image tiles of the graph and the action framework.
The Grouped Graph demo shows how to
combine navigation in a grouped graph which is provided by the
GroupNavigationMode with incremental changes
of the layout. This is a scenario for applications, which want to provide a drill-down feature.
The incremental layout is realized by a custom servlet, the
GroupedGraphServlet which inherits from the UpdateServlet. Note that the sources
are not available online, i.e. you cannot get them from live.yworks.com. In order to
execute customized actions on the graph, if a group node is opened for example, the demo uses custom request
URIs like /incremental/closeGroup which are mapped to the customized servlet. Note that
/closeGroup is still available and maps to the standard UpdateServlet.
The Graph Editor demo application
shows that it is possible to encapsulate a complex HTML DOM structure into a single custom
Dojo widget, the GraphEditor widget which uses several child widgets. Its
uncompressed source code is available
in the javascript/demos/widget subdirectory of the deployed yFiles AJAX web application.
Note that the sources are not available online, i.e. you cannot get them from
live.yworks.com. Among several other things the source code shows how to connect events
in the GUI to actions on the graph and vice versa. It also uses a hierarchy manager and an edit mode.
The template for the Graph Editor widget can be found in a separate
HTML file.
The Collapsible Tree demo application is similar to the application for the second tutorial. It uses the same server side, but a more complex client. This demo features another kind of drill-down for the special case of tree-shaped graphs, whereas the drill-down in the Grouped Graph demo can be used for any graph.
The Swim Lanes demo application showcases using server actions and view configurators.
The yFiles AJAX web application archive contains all the resources
you need to run a web application using yFiles AJAX except for the y.jar file
containing yFiles (for Java) and possibly your yFiles AJAX license file. These can be added
manually or by using ant as described in the
installation instructions.
You can unpack the complete yFiles AJAX web application using ant in the
top level directory of the distribution with the target unzip-war. Most
archiving tools should also be able to unpack the web application archive
yfiles-ajax.war which is located in the subdirectory webapp.
The server side classes for yFiles AJAX including the servlets are packaged as a jar file,
yfiles-ajax.jar. The server side code for the yFiles AJAX demos is packaged
as a separate jar file, yfiles-ajax-demos.jar. The classes in the
yfiles-ajax.jar rely on some other jar files, which ship with yFiles AJAX and
the y.jar file from the lib subdirectory of your yFiles for Java
distribution. If you installed the yFiles AJAX web application containing the tutorials,
the demos and so on, all of the needed jar files can be found in the WEB-INF/lib
subdirectory of the deployed web application. Deploy all of these jars except
yfiles-ajax-demos.jar to the WEB-INF/lib subdirectory of your
web application.
If you want to run the demo applications with yFiles for Java 2.5, you can adapt the
server side sources for the demo applications and compile them with yFiles for Java 2.5.
Deploy the Java class files to the WEB-INF/classes directory of your web
application and do not deploy the yfiles-ajax-demos.jar file. The server
side sources for the demo applications are located in the src directory
of the unpacked web application archive yfiles-ajax.war.
A complete example for the entries in the web.xml file of your application
can be found in the WEB-INF subdirectory of the deployed yFiles AJAX web application.
Merge the needed entries into your own WEB-INF/web.xml file.
The yFiles AJAX servlets are implemented in a way which allows you to put them into a virtual
subdirectory of your web application, if this is desirable. You can for example add the prefix
/yfiles to all yFiles AJAX requests in the web.xml file, such that
/getImage becomes /yfiles/getImage, /createNode becomes
/yfiles/createNode and so on. In this case you have to adjust the yFiles AJAX
components you are using on the client accordingly, e.g. for an HTML page in the root directory
of your web application, which uses a yFiles AJAX GraphCanvas, add the baseUrl="yfiles"
attribute to the HTML markup of the div with the
dojoType="yfiles.client.tiles.widget.GraphCanvas" attribute.
Deploy your license file to the WEB-INF subdirectory of
your web application. The default name of the file is yfiles-ajax-license.xml.
If you want to use another name, you can do so by specifying the alternative name
as the value of the context parameter yfiles.ajax.license.file.name of your
web application. If for example your license file is called myLicense.xml add
the follwing XML snippet to your web.xml file between the display-name
element and the first servlet element.
<context-param>
<param-name>yfiles.ajax.license.file.name</param-name>
<param-value>myLicense.xml</param-value>
</context-param>
yFiles AJAX is deployed as a layered build on top of Dojo 1.2.1 with the provided build tool using this profile. Details on the Dojo build tool can be found at the Dojo website. At the time of this writing they can be found in "documentation" >> "The Book of Dojo, 1.0" >> "Part 4: Testing, Tuning and Debugging" >> "The Package System and Custom Builds".
The profile defines three layers, yfiles-ajax-prerequisites.js,
yfiles-ajax-base.js and yfiles-ajax-complete.js.
yfiles-ajax-prerequisites.js layer contains all Dojo sources which are
not part of the Dojo core, but needed by yFiles AJAX.
yfiles-ajax-base.js contains
no Dojo sources, but all client side sources for yFiles AJAX except the demo sources.
yfiles-ajax-complete.js contains all prerequisites and all yFiles AJAX
client side sources including the demos.
You can use the yfiles-ajax-base.js layer on top of your custom Dojo layers, if they
are also based on Dojo 1.2. In addition to just copying the layer files to your Dojo directory,
please do also copy the yfiles-ajax*.js files from the nls subdirectory,
which are generated by the build tool, to your dojo/nls directory.
If you are using a newer version of Dojo for your build or patched Dojo 1.2.1 you may also be able to use yFiles AJAX on top of that, if there are no incompatibilities.
Styles for yFiles AJAX widgets have been separated into necessary style (e.g. positioning
of tiles in the graph canvas) and optional style (e.g. color of selected graph elements
in the graph canvas). The latter can be customized by changing the centralized yfiles AJAX style
sheet or adding custom rules for the classes used for yFiles AJAX to your own style sheet.
The style sheet for yFiles AJAX can be found
here. There is a
separate style sheet for the
client side classes in the demos namespace including the Graph Editor.
Note that the style sheets for yFiles AJAX follow the theme approach as found in Dojo.
All rules only apply, if the yfiles class is present at the target DOM element. This
is the so-called theme in Dojo terminology. Thus, the rules can be switched on or off by
adding or removing the yfiles class to or from the body tag of the HTML
page, since all DOM elements inherit the class from their ancestors and eventually from the
body tag. By defining similar rules with a different common class like
myCompany you can also switch the appearance back and forth. More information on
this topic is also available at the Dojo website.
At the time of this writing they can be found in "documentation" >> "The Book of Dojo, 1.0" >>
"Part 2: Dijit" >> "Themes and Design".
Note that highlighting nodes or edges in a graph canvas currently uses div elements which are invisible, if you do not use the yFiles AJAX style sheet or define your own CSS rule for div elements with the "yFilesGraphCanvasOverlay" class.
In order to display and interact with a graph on the client side in a web application using yFiles AJAX, the graph needs to be cached for the session of the client in the first place. As a second step a GraphCanvas widget can actually be configured to display the cached graph via its setPath function. There are two steps involved in order to allow for customization of the first step.
In the easiest case, the graphs are known in advance. In this case they can be saved as files to the
/resources/graphs/ and thus can be provided by the resource loading mechanism implemented
in the LoaderServlet. This is done in the Graph Viewer and Graph Editor demos. In this case a call to
the setPath of the GraphCanvas with the base name of the graph file, like
e.g. "computers.ygf", suffices. The GraphCanvas calls the load function of its
underlying graph, which sends a loadGraph request to the server. In the standard configuration
this request is handled by the LoaderServlet, which checks whether a graph with the given name
is already cached for the session of the request. If this is not the case, it tries to load the graph as
a resource from the /resources/graphs/ directory.
There is an optional parameter for reloading graphs from the file system, if they are already cached.
The Collapsible Tree demo is an example for working with a dynamically created graph. The client sends
an initializeGraph request to the server which is handled by the initializeGraph
method in the TreeCollapserServlet. It creates a graph and caches the graph for the session
of the request using the cacheGraph method inherited from the BaseServlet. When
the request returns to the client the GraphCanvas widget is configured to display this graph
by using the setPath function.
yFiles for Java provides some display like adding drawables to the view and configuring the
renderer to display edge crossings using bridges, which are configured using the
y.view.Graph2DView instance used to display the graph or its renderer.
In a web application based on yFiles AJAX, you do not have access to a Graph2DView
instance. In fact the Graph2DView class is used for rendering the graph on the
server side of yFiles AJAX, but there is typically more than just one graph view instance and
these instances are transient. In other words: the situation is not as easy as in a desktop
application using yFiles for Java.
Since version 1.2 of yFiles AJAX there is a new feature, which enables using the view
features described above in a straight forward way regardless of the more difficult setting.
There is a new public static method addViewConfigurator at the BaseServlet.
It takes an object which implements the ViewConfigurator interface. The interface
has just one method configureView which is called with a Graph2DView
immediately before the view is used to render a graph. Adding a view configurator in your server
side code can be done as follows.
BaseServlet.addViewConfigurator(graph, new ViewConfigurator() {
public void configureView(Graph2DView view) {
// do something with the view
}
});
View configurators can also be removed again. The ConfigureBridgesAction in the
Swim Lanes demo is an example for switching on or off displaying edge crossings as bridges.
With version 1.2 a new framework for adding custom actions to the server side of an application based on yFiles AJAX and handling them from the client side has been added. It removes the need to add new servlets on the server side and to do the housekeeping on the client side after graph changes on the server. The Swim Lanes demo application is an example for using the framework.
There is a new generic servlet, the ActionServlet which dispatches requests
for custom actions to implementations of the ActionHandler interface. The
ActionHandler implementations are registered for an action id by means of
initialization parameters of the ActionServlet.
On the client side there is a new ServerAction class which defines the
context for a custom action, wraps the server call and takes care of updating client
side data for the hit test and the hierarchy manager (configurable). It can also
trigger the refresh of a canvas.
Instead of using new servlets, the server side functionality is implemented by
custom ActionHandler instances. They are called from the ActionServlet
with an ActionContext instance, which provides the context from the
client, and a ClientControl instance which can be used by the action
handler in order to control the client side post-processing after the server side action
has been performed.
A custom action is identified by a unique id and implemented by a combination of
a server side class implementing the
com.yworks.yfiles.server.tiles.servlet.action.ActionHandler interface
and a suitably configured instance of the client side
yfiles.client.tiles.ServerAction class. The class implementing the
ActionHandler interface additionally needs to have a no-arguments
constructor.
The server side class implementing the action handler for the action identified by
an id is registered with the ActionServlet by means of an initialization parameter
specified in the web.xml file.
...
<servlet>
<servlet-name>ActionServlet</servlet-name>
<display-name>Action Servlet</display-name>
<description>handles custom actions</description>
<servlet-class>com.yworks.yfiles.server.tiles.servlet.action.ActionServlet</servlet-class>
<init-param>
<param-name>yworks.demos.actions.swimlaneLayout</param-name>
<param-value>com.yworks.yfiles.server.tiles.demos.SwimLaneLayoutAction</param-value>
</init-param>
</servlet>
...
The above snippet defines an action implemented by the class
com.yworks.yfiles.server.tiles.demos.SwimLaneLayoutAction and identified by
the id yworks.demos.actions.swimLaneLayout by using an initialization parameter
of the ActionServlet. When the ActionServlet is initialized it creates
instances of the action handlers specified as above using their no-arguments constructors and
associates them with the corresponding ids. Later calls to the ActionServlet with the id
yworks.demos.actions.swimLaneLayout will then be dispatched to the instance created
at initialization time of the servlet.
The action handler instance which implements the custom action has access to the context
of the action specified at the client side by means of an ActionContext
instance which gets passed to it by the ActionServlet. Usually, a graph is available
from the context. The client side can also specify sets of nodes and edges. In this case
they are also available to the server side action from the context. Moreover, the context
can be queried whether certain resources like a hit test or a hierarchy manager are available
on the client side.
The action handler is also provided with a ClientControl instance. It is
used to control the post-processing on the client side after the request to the
ActionServlet has returned. While the ActionContext is an immutable
object, the action handler can change the settings of the client control instance.
For example, it can compute a new set of nodes and set it on the control to be returned
to the client side. An example for such an action is the SelectReachableNodesAction
used in the Swim Lanes demo. The ClientControl is by default initialized
to update the client side hit test data, if a hit test instance is available at the client side.
The action can change this setting. Similar behavior is implemented for the hierarchy manager,
the selection and the canvas. The following code is used in the action handler for selecting
the nodes, which are reachable from a given node, which is used in the Swim Lanes demo application.
public void handleAction(ActionContext context, ClientControl control) {
Graph2D graph = context.getGraph();
NodeList nodesIn = context.getNodes();
if (graph == null || nodesIn.size() != 1) {
control.setUpdateSelection(false);
return;
}
boolean[] reached = new boolean[graph.N()];
Node startNode = nodesIn.firstNode();
GraphConnectivity.reachable(graph, startNode, true, reached);
NodeList nodesOut = control.getNodes();
nodesOut.clear();
for (NodeCursor nodeCursor = graph.nodes(); nodeCursor.ok(); nodeCursor.next()) {
Node node = nodeCursor.node();
if (node != startNode && reached[node.index()]) {
nodesOut.add(node);
}
}
}
The graph and the nodes selected on the client side are fetched from the context, the reachable
nodes are computed and set for the response using the control.
Another interesting feature of the action framework is used in the action handler for
the action to configure bridges for the Swim Lanes demo application. The corresponding
ServerAction instance on the client specifies the canvas since the canvas
needs to be refreshed when bridges are switched on or off. Bridges have no influence on
the on the bounds of the nodes or the control points of the edges. Thus the hit test
information does not need to be updated when running this action. Therefore the action handler
switches off updating the client side hit test using control.setUpdateHitTest(false);.
The client side wrapper for a server side action is an instance of the class ServerAction.
It has a key-word-arguments-style constructor like e.g. a dojo.xhrPut call. The following
code snippet is a slightly simplified example for creating a ServerAction instance from
the Swim Lanes demo.
selectReachableNodesAction = new yfiles.client.tiles.ServerAction({
id : 'yworks.demos.actions.selectReachableNodes',
graph : graph,
selection : editMode.getSelection()
});
If you call the run() function on the above created action, it will send a request
to the ActionServlet to perform the action registered with the id
yworks.demos.actions.selectReachableNodes on the server. The
selectReachableNodesAction on the client takes care of getting the currently selected
objects from the GraphSelection instance obtained by editMode.getSelection() in
order to send them to the server as part of the request. When the response for the request arrives from
the server, the selectReachableNodesAction will update the GraphSelection
according to the node ids, which are sent back from the server. Since neither a canvas, a hit test, nor
a hierarchy manager is available for the selectReachableNodesAction, there will be no
refresh of a canvas and no update of a hit test or hierarchy manager.
The ServerAction also provides hooks for functions to be called immediately before
a request is sent to the server and immediately after a response has arrived. They can be specified
with the preRun and postRun key words in the constructor, respectively. By the
way, the key word-argument pairs recognized in the constructor also have corresponding getters and setters.
The preRun and postRun functions will be executed in the scope of the
ServerAction instance, i.e. the ServerAction instance is accessible using
this inside these callbacks. The treasure hunt tutorial contains
an example for using a custom response from the server side action.
var distances;
var hideTreasureAction = new yfiles.client.tiles.ServerAction({
id : 'yworks.demos.actions.hideTreasure',
graphName : 'treasure-islands.graphml',
postRun : function() {
// Parse the custom response from the server as JSON string.
distances = dojo.fromJson(this.getCustomResponse());
}
});
The preRun callback is expected to return a boolean. If it returns false, the
action is canceled immediately. No request is sent to the server. There is an example for
canceling the run call in the Swim Lanes demo.
selectReachableNodesAction = new yfiles.client.tiles.ServerAction({
id : 'yworks.demos.actions.selectReachableNodes',
graph : graph,
selection : editMode.getSelection(),
preRun : function() {
// Cancel the action, if the selection does not contain exactly one node.
return this.getSelection().getSize() == 1;
}
});
The Swim Lanes demo application uses four different ServerAction instances for performing a complete layout, an incremental layout, configuring bridges and selecting the nodes reachable from a given node. These actions demonstrate different aspects of the action framework. The following code snippet shows the creation of the action for doing an incremental layout which is triggered when the user moves some nodes.
changeLaneAction = new yfiles.client.tiles.ServerAction({
id : 'yworks.demos.actions.changeLane',
canvas : canvas,
selection : editMode.getSelection()
});
The canvas is specified which automatically triggers a refresh of the canvas after the action
was performed. Since a canvas always has a hit test, the hit test data is also updated. Otherwise
you could not select a node which changed its position after performing the layout. The nodes
which were moved are those nodes which the user selected before. Thus the selection maintained by the
edit mode is used to specify the nodes which need to change their lane for the server side.
Note that editMode.getSelection() returns a GraphSelection instance
not the currently selected set of nodes. This instance is queried for the current selection whenever
the action runs.
For more details on the possibilities of the action framework please consider the Server Side API Documentation and the Client Side API Documentation.
Copyright © 2006-2008 yWorks. All Rights Reserved.