Using hyperlinks with nodes, edges and labels
Tips & TricksSummary
Description
Using the built-in anchor functionality provided by the Flex framework
The Flex framework provides a built-in anchor functionality that can be used with the context menu (right-click) of the label: simply include HTML tags within the label string. However, there is one drawback: If you hover over a label with a html link that is located over a movable item, you will notice that two cursors are displayed at the same time.
Using InputModes to follow a hyperlink
If only a single hyperlink should be followed for the link, use either the click
event of the ClickInputMode (for left click events)
or the CanvasContextMenuEvent event of the ContextMenuInputMode (right click) to follow urls
instead of using embedded html tags.
The GraphCanvas demo shows how this is achieved for an url entry in the context menu.
A good way to map URLs to items is using a mapper. The following code shows how to create, register and fill a mapper for nodes:
// create a mapper and register it to the graph
graphCanvas.graph.mapperRegistry.addMapper( "nodeURIs", new DictionaryMapper() );
// retrieve the mapper
var dataMapper:IMapper = graphCanvas.graph.mapperRegistry.getMapper( "nodeURIs" );
// register an URL-String to the node "aNode"
dataMapper.mapValue(aNode, encodeURI("http://an.url.as.string"));
To retrieve the URL mapped to the node the mouse points on, first retrieve the display objects pointed on, then get the item represented by these objects, then retrieve the URL from the map:
/**
* Gets the url belonging to the canvas object under the mouse pointer
* @param x The mouse cursor's x position in world coordinates
* @param y The mouse cursor's y position in world coordinates
* @return the URL as String or null
*/
private function getURLunderCursor(x:Number, y:Number):String {
// Gets the canvas objects under the mouse pointer
var it:Iterator = graphCanvas.getCanvasObjects( x, y ).iterator();
var url:String;
// looks for an object which has a url mapped to
while( it.hasNext() ) {
var hitObj:ICanvasObject = ICanvasObject( it.next() );
var item:Object = hitObj.userObject;
url = getURL( item );
if( null != url ) {
break;
}
}
return url;
}
/**
* Gets the URL mapped to the item
* @param item the item for which the URL is to be retrieved
* @return the URL as String or null
*/
private function getURL(item:Object):String {
var nodeUrlMapper:IMapper = graphCanvas.graph.mapperRegistry.getMapper( "nodeURIs" );
var nodeData:String = nodeUrlMapper.lookupValue( item ) as String;
if (null != nodeData) {
return decodeURI( nodeData );
}
return null;
}
For opening the link upon a mouse click (left click), one has to add a listener which handles mouse clicks to the ClickInputMode.
This listener uses the above methods to retrieve the URL for the clicked item and opens the link.
...
// inputMode is the main input mode registered to the graph, mostly a GraphEditorInputMode
inputMode.clickInputMode.addEventListener(ClickEvent.CLICK, onMouseClick );
...
/**
* Gets the URL mapped to the clicked item. If there is any: open the link
*/
private function onMouseClick( evt:ClickEvent ):void {
var url:String = getURLunderCursor( evt.clickPoint.x, evt.clickPoint.y );
if (url != null) {
var req:URLRequest = new URLRequest( url );
flash.net.navigateToURL( req, "_blank" );
}
}
Opening links for a context menu selection (right click) requires a listener which handles opening of a contex menu to the ContextMenuInputMode.
This listener will add an entry for the link to the context menu and registers a listener for that which opens the link upon selection:
...
// inputMode is the main input mode registered to the graph, mostly a GraphEditorInputMode
inputMode.contextMenuInputMode.addEventListener(CanvasContextMenuEvent.MENU_SELECT,onContextOpened);
// graphCanvas is the GraphCanvasComponent the graph is displayed on
inputMode.contextMenuInputMode.menu = graphCanvas.contextMenu;
...
/**
* Called, when a Context Menu was opened. If an URL is mapped to the clicked item
* a context menu entry for the link is created, with an appropriate listener associated.
*/
private function onContextOpened(evt:CanvasContextMenuEvent):void {
var cm:ContextMenu = evt.contextMenuOwner.contextMenu;
cm.hideBuiltInItems();
var url:String = getURLunderCursor( evt.worldX, evt.worldY );
// If an URL was found: add a menu entry and register a listener which will follow the link
if( null != url ) {
var cItem:ContextMenuItem = new ContextMenuItem( "Goto "+url );
cItem.addEventListener( ContextMenuEvent.MENU_ITEM_SELECT,
function( evt:ContextMenuEvent ):void {
var req:URLRequest = new URLRequest( url );
flash.net.navigateToURL( req, "_blank" ); // follow the link
}
);
cm.customItems.push( cItem );
}
}
Serialization of URLs
URLs for nodes, edges or labels can be (de)serialized as additional GraphML attributes. See the knowledge base article Transfer of additional data between server and client for details. Also, the GraphCanvas demo shows how to configure the RoundtripHandler and the corresponding mappers.