The following yFiles AJAX tutorials are contained in this document:
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 that is part of the yFiles AJAX API 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 and tutorials which ship with yFiles AJAX is included in the distribution:
demos/web-content/html
demos/web-content/javascript/demos
demos/src
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).
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. See also the sections "Using an IDE" and "Creating an Eclipse project for the yFiles AJAX demo web application" of the readme file.
lib/java
of the yFiles AJAX distribution) 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
which can be found in the top-level directory
of the yFiles AJAX distribution to the WEB-INF
directory of your new web application.
WEB-INF/web.xml
file of your web application should contain
the mappings for the requests used by your application and the corresponding servlets.
This example is quite small using just the TileServlet (which
you always need if you use a GraphCanvas on the client side) and the LoaderServlet. It suffices for this
tutorial. A commented complete example can be found in
the lib
directory of the yFiles AJAX distribution.
lib/javascript
as subdirectories
javascript/dojo
, javascript/dijit
and javascript/dojox
.
demos/web-content/resources/graphs
directory from the yFiles AJAX distribution
as a deployed subdirectory resources/graphs
. This directory is used for loading graphs from
files on the server side. The graph to be displayed in this tutorial will be loaded from a file. The name
and path for the directory containing the GraphML files which can be loaded is fixed.
In step 2 of this tutorial we'll add the index.html file. The resulting directory structure of your web application should look like this.
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> var dojoConfig = { isDebug: false, baseUrl: "../javascript/", tlmSiblingOfDojo: false, packages: [ { name: "dojo", location: "dojo" }, { name: "dijit", location: "dijit" }, { name: "dojox", location: "dojox" }, { name: "yfiles", location: "yfiles", main: "yfiles" }, { name: "demos", location: "demos", main: "demos" } ] }; </script> <script data-dojo-config="async: true" src="../javascript/dojo/dojo.js"></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.
Now we add the layer (Dojo term for a packaged JavaScript source file, more information can be found in the yFiles AJAX Developer's Guide in this section), which contains the yFiles AJAX client side components. Therefore we load an additional JavaScript file by adding the following line below the line for adding Dojo itself.
<script src="javascript/dojo/yfiles-ajax.js"></script>
Now you can add the GraphCanvas
to the body of the page. The GraphCanvas is a Dojo widget
(reusable user interface element).
It uses the space provided by its parent element in the HTML page. 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 data-dojo-type="yfiles/client/tiles/widget/GraphCanvas" id="canvas" data-dojo-props="path:'computers.graphml'"></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.
To create the dojo widget from the <div> element, we need to invoke dojo's parser after the DOM and all required AMD modules have been loaded:
require( [ "dojo/ready","dojo/parser"], function(ready, parser) { ready(function() { parser.parse(); }); } );
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 reference the graph canvas using custom JavaScript code we add two zoom buttons to the page.
<div> <button>Zoom In</button> <button>Zoom Out</button> </div>
You can get a reference to a specific Dojo widget with a known id by using
registry.byId()
(provided by the dijit/registry
module).
The graph canvas has a readonly attribute zoom
holding the current zoom factor and a function setZoom()
for setting
a new zoom factor. In addition, the canvas offers convenience functions to increase and decrease
the zoom level: increaseZoom(factor)
and decreaseZoom(factor)
.
We will call these functions when the zoom buttons are clicked:
require( [ "dojo/ready","dojo/parser","dojo/on","dojo/dom","dijit/registry","yfiles/client/tiles/widget/GraphCanvas"], function(ready, parser, on, dom, registry) { var init = function() { var canvas = registry.byId('canvas'); on(dom.byId("zoomIn"),"click",function() { canvas.increaseZoom(2.0); } ); on(dom.byId("zoomOut"),"click",function() { canvas.decreaseZoom(2.0); } ); }; ready(function() { parser.parse(); init(); }); } );
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 demos/web-content/html/basic.html
in the yFiles
AJAX distribution.
NOTE: The graph canvas has an additional parameter baseURL:'..'
in the
HTML page for this tutorial at the location in the yFiles AJAX distribution.
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 html
. 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. 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 run 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 order to be able to define a callback for the event that the graph was loaded.
In the body of the page, we use the canvas adapted as 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 data-dojo-type="yfiles/client/tiles/widget/GraphCanvas" id="canvas" data-dojo-props="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.
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> require(["yfiles/client/tiles/ServerAction"], function(ServerAction) { var canvas, hint, distances; var hideTreasureAction = new ServerAction({ url : '../yFilesAction', id : 'yworks.demos.actions.hideTreasure', graphName : 'treasure-islands.graphml', postRun : function() { distances = JSON.parse(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
provided 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.
onClickNode
is called when a node is clicked.onMouseOverNode
is called when the mouse enters a node.onMouseOutNode
is called when the mouse leaves a node.onTapNode
is called when a node is tapped.
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
, onTapNode
, and
onMouseOutNode
events of the graph canvas. The script block now looks like this:
require([ "dojo/ready", "dojo/parser", "dojo/dom", "dojo/on", "dojo/aspect", "dojo/json", "dojo/_base/lang", "dijit/registry", "yfiles/client/tiles/widget/GraphCanvas", "yfiles/client/tiles/ServerAction"], function(ready, parser, dom, on, aspect, JSON, lang, registry, GraphCanvas, ServerAction) { var canvas, hint, distances; var hideTreasureAction = new ServerAction({ url : '../yFilesAction', id : 'yworks.demos.actions.hideTreasure', graphName : 'treasure-islands.graphml', postRun : function() { distances = JSON.parse(this.getCustomResponse()); } }); function init() { canvas = registry.byId('canvas'); hint = dom.byId('hint'); on(canvas, 'PathSet', onPathSet); canvas.setPath('treasure-islands.graphml'); // make zoomToPoint the default behaviour, for simple zoom hold the ctrl key canvas.zoomToPointRecognizer = function(evt) { return !evt.ctrlKey; }; } function onPathSet() { hideTreasureAction.run(); on(canvas, 'ClickNode', feedback); on(canvas, 'TapNode', feedback); on(canvas, 'MouseOutNode', function() { hint.innerHTML = ' '; }); } function feedback(id) { // TODO } ready(function() { parser.parse(); init(); }); } );
The effect of a call like on(canvas, 'ClickNode', feedback);
is that each time the onClickNode
function of the canvas is called, the
feedback
function is 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 again.
For providing the feedback to the user, 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! //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 obtain the distance from the node where the user 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 looks like this (use the view source feature of your browser).
NOTE: The complete tutorial HTML page is located in the subdirectory html
in the yFiles AJAX web application. 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 previous 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 need to 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 yFiles for Java
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
class in another private helper method.
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 structure 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. Instead, 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 action 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 of the
HideTreasureAction
can be found in the demos/src
folder in package
com.yworks.yfiles.server.tiles.demos
.
More information on the action framework is available in this section of the Developer's Guide for yFiles AJAX.
The Swimlanes 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, most nodes should be hidden.
For this tutorial, we want to use a different page layout. The graph canvas should use the whole page, and adapt it's size to page resize events.
From a high-level perspective, we have the following new requirements.
Unless the action framework (described in the previous tutorial) is used, extending the server side typically means adding new servlets and servlet mappings to the web application. In this case we add the 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
,
we create the graph programmatically and cache it
using the fixed name "CollapsibleTree".
Creation and caching of the initial graph is triggered by the "initialize" request.
To store the graph in the session, class BaseServlet
provides the method cacheGraph()
.
Instead of creating the graph structure on the fly, it would also have been possible to
retrieve the graph from another data source, e.g. from a database.
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 to graph events by connecting to the
graph events of interest. These events are fired by the graph canvas.
As an example, please have a look at the sources of the
TutorialGraphListener module, which
connects to the onClickNodeLabel
event.
Copy the file TutorialGraphListener.js
to a subdirectory tutorials
of the javascript
. The module
can then be loaded as an AMD module from tutorials/TutorialGraphListener
.
The TutorialGraphListener
is defined using a dojo declare()
call for creating classes.
The declare is provided by the dojo/_base/declare
AMD module:
define(["dojo/_base/declare"], function(declare) { return declare(null, { ... }) } );The constructor for a new instance is the
constructor
function. The TutorialGraphListener
stores a reference to the canvas and calls _initializeGraph()
in order to set up the initial graph.
As a third step, it connects the onClickNodeLabel
function of the canvas with its own
onClickNodeLabel
function. This causes the onClickNodeLabel
function of the
TutorialGraphListener
to be called once after each call to onClickNodeLabel
on the canvas, passing 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 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 to maintain his mental map
of the graph after the expand/collapse 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("tutorials", "../tutorials"); dojo.require("tutorials.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 might not have been created yet. We create the listener
on page load using dojo.addOnLoad()
. This way, we can be
sure that the canvas widget is already constructed. To this end, 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 tutorials.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 allowing the canvas to use the whole visible area can be achieved by
removing the div
enclosing the graph canvas, and by 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.
You will also find the sources in the distribition at demos/web-content/html/extended.html
.
Copyright © 2006-2013 yWorks GmbH. All Rights Reserved.