Donnerstag, Juli 26, 2007

Tree view Ajax control update

The tree view control was introduced some time ago and some details of its implementation can be found at http://ajaxaspects.blogspot.com/2006/01/tree-view-ajax-control.html or in the book at http://www.mathertel.de/AJAXEngine/documentation/AJAXeBook.aspx.

Now there is an update available and also a step by step sample how to use this control inside your web application.

The sample page can be found at: http://www.mathertel.de/AJAXEngine/S03_AJAXControls/TreeView.aspx.

1. Building a web service

Using Ajax with a tree view control is based on the idea that the full data that builds a complete tree might have a size that cannot be downloaded to the browser in one time. The server therefore has to offer a method that enables downloading fragments of a hierarchic data structure exactly in that moment when the user opens a new sub tree.

The tree view Ajax control binds to a webservice with only one function GetSubNodes(string path) that has to be built for your specific solution. If you like you can also use a different name for the method.

The structure of the XML node that must be returned by this method looks like this:

<tree> <folder name="AK" title="Alaska">
<file title="Aguila" name="ZIP85320" link="http://weather.aol.com/main.adp?location=USAZ0001"/> <file title="Ajo" name="ZIP85920" />
<file name="Redmond" img="redfile" />

<file name="Alpine" /> <file name="Yuma" /> </tree>

The outer element must be a <tree> node that contains <folder> and <file> nodes.

As you can see the name attributes do have a special purpose in this structure because the values of these nodes together and separated by slashes will build a path to each available element for example "/AZ/Ash Fork".

When clicking onto folders and files this path will be used for loading a subtree or for the events that are published when a final <file> node is clicked.

The title attribute is optional. Its text will be displayed behind the icon. If it's not present the name will be used instead.

The link attribute can be used when a click on a final node should just open a regular hyperlink.

When there is no link present on a file node an OpenAjax event "de.mathertel.treeview.click" with the path of the node in the data is published. You can register to this event for catch all clicks if no navigation is required.

You can find a webservice implementation here and here.

Having built such a web service most of the work is done.

2. importing the webservice

The webservice must be made available on the page containing the Ajax tree view control by using a simple JavaScript include:

<script type="text/javascript"
src="../ajaxcore/GetJavaScriptProxy.aspx?service=../S03_AJAXControls/TreeView.asmx"></script>

Now the webservice is available through the proxies.TreeView object and the GetSubNodes method can be called by using the generated proxies.TreeView.GetSubNodes() function.

3. embedding the Ajax tree view control

The control is implemented as a user control in the file ~/controls/TreeView.ascx. If you use Visual Studio 2005 you can drag this file onto a page and the control will be registered for this page or you can register the control by using a @Register tag at the beginning of the page:

<%@ Register Src="../controls/TreeView.ascx" TagName="TreeView" TagPrefix="ajax" %>

The other way to register a user control is putting an option into the web.config file. This is the better solution if you want to reuse the control on multiple pages and like to use the same prefix all over the web application.

<configuration>
  <system.web>
    <pages>
      <controls> 
<add src="~/controls/TreeView.ascx" tagName="TreeView" tagPrefix="ajax"/>

The control itself can be used now: 

<ajax:TreeView ID="TreeView1" runat="server" 
  service="proxies.TreeView.GetSubNodes" title="Cities in the USA" />

You can see the complete source of the page by using this link: [view source of TreeView.aspx].

4. CSS and specific icons

Some tree view might not only use folders and files so there is a special feature for that too.

The CSS code that is used by the tree view control is shown here:

div.TreeView .du {height:18px;overflow:hidden;cursor:hand; 
  background-image:url(controls/images/dc.png);background-repeat:no-repeat} div.TreeView .do {height:18px;overflow:hidden;cursor:hand;
  background-image:url(controls/images/do.png);background-repeat:no-repeat} div.TreeView .dc {height:18px;overflow:hidden;cursor:hand;
  background-image:url(controls/images/dc.png);background-repeat:no-repeat} div.TreeView .de {height:18px;overflow:hidden;
background-image:url(controls/images/de.png);background-repeat:no-repeat} div.TreeView .fl {height:18px;overflow:hidden;
background-image:url(controls/images/file.png);background-repeat:no-repeat} div.TreeView .ft {padding-left:40px} div.TreeView .subframe {margin-left:18px;}

Using these short classnames for attaching the style results in small html code fragments and you can link to the right images just by modifying the style rules. I put this baseline definition into the main css include file of the web application.

By specifying the img attribute on a file node in the data that is returned from the server another classname can be included for the ft-class elements. To avoid individual image tags in the tree view this classname extension also is handled by using a style rule that you can add:

div.TreeView .fl.redfile {background-image:url(../controls/images/redfile.png)}

This definition can be found in the sample page itself but you can also put it into the mail css include file if you like. Search for Redmond(WA) to see it work.

5. handling the events

If you just like to show information in a tree fashion and like to use hyperlinks on the file nodes you don't need to have a look at the eventing system that is also built in.

When clicking a file node and if there is no hyperlink set then the tree view controls publishes an event that event handlers can catch. The eventing system that is used here is the OpenAjax compatible event hub. You can find the documentation about it on the http://www.OpenAjax.org site and the implementation is part of the ~/controls/jcl.js file that is included automatically.

To register for such an event you need a little bit of JavaScript code:

// a function that will catch the tree events by listening to de.mathertel.treeview.**.
function showTreeEvent(name, data) {
  alert("click on " + data);
} // showTreeEvent

OpenAjax.hub.subscribe("de.mathertel.treeview.**", showTreeEvent);

The OpenAjax.hub.subscribe is registering the showTreeEvent function and this function will be passed the name of the event and the path in the data payload.

About the updated features

New to the current implementation is the support for the link attribute in the <file> elements and the publishing of events when clicking final nodes.

If you want to see more features or want to have more supported scenarios then let me know by using the feature request function on http://sourceforge.net/projects/ajaxengine/.

Kommentare:

Anonym hat gesagt…

I'm italian.
Very good treeview.
I have one question: if I want to put a different image also in folder? Is possible?

Thanks
Sara

Anonym hat gesagt…

I'm italian.
Very good treeview.
I have one question: if I want to put a different image also in folder? Is possible?
Like this:

<pre class="code"><p><tree>
<folder name="AK" img="redfile" title="Alaska"><br> <file title="Aguila" name="ZIP85320" link="http://weather.aol.com/main.adp?location=USAZ0001"/>
<file title="Ajo" name="ZIP85920" /><br> <file name="Redmond" img="redfile" /><br></p><p> <file name="Alpine" />
<file name="Yuma" />

</tree></p></pre>

Thanks
Sara

MatHertel hat gesagt…

Hi Sara,
the folders do't accept the img attribute in the current implementation but I think you can make it by extending the xslt arround line 85 in the treeview.js file.

Anonym hat gesagt…

Yes, I try to do this, but the image don't appear (I also add link
to the folder)

xslt: "<?xml version='1.0' ?><xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\
<xsl:template match='/tree'><xsl:apply-templates /></xsl:template>\
<xsl:template match='folder'><div class='du'><xsl:attribute name='class'>du<xsl:value-of select='@img' /></xsl:attribute><xsl:attribute name='name'><xsl:value-of select='@name' /></xsl:attribute><span class='ft'>\
<xsl:choose>\
<xsl:when test='@link'><a><xsl:attribute name='href'><xsl:value-of select='@link' /></xsl:attribute><xsl:attribute name='target'><xsl:value-of select='@target' /></xsl:attribute>\
<xsl:choose><xsl:when test='@title'><xsl:value-of select='@title' /></xsl:when><xsl:otherwise><xsl:value-of select='@name' /></xsl:otherwise></xsl:choose>\
</a>\</xsl:when>\
<xsl:otherwise><xsl:choose><xsl:when test='@title'><xsl:value-of select='@title' /></xsl:when><xsl:otherwise><xsl:value-of select='@name' /></xsl:otherwise></xsl:choose>\
</xsl:otherwise></xsl:choose>\
</span></div><div class='subframe' style='display:none'></div></xsl:template>\
<xsl:template match='file'><div class='fl'>\
<xsl:attribute name='class'>fl <xsl:value-of select='@img' /></xsl:attribute>\
<xsl:attribute name='name'><xsl:value-of select='@name' /></xsl:attribute><span class='ft'>\
<xsl:choose>\
<xsl:when test='@link'><a><xsl:attribute name='href'><xsl:value-of select='@link' /></xsl:attribute><xsl:attribute name='target'><xsl:value-of select='@target' /></xsl:attribute>\
<xsl:choose><xsl:when test='@title'><xsl:value-of select='@title' /></xsl:when><xsl:otherwise><xsl:value-of select='@name' /></xsl:otherwise></xsl:choose>\
</a>\</xsl:when>\
<xsl:otherwise><xsl:choose><xsl:when test='@title'><xsl:value-of select='@title' /></xsl:when><xsl:otherwise><xsl:value-of select='@name' /></xsl:otherwise></xsl:choose>\
</xsl:otherwise></xsl:choose>\
</span></div></xsl:template>\
</xsl:stylesheet>"

I'm not very expert for xls language.

Thank
Sara