// TreeView.js // Javascript Behaviour for the TreeView Control // Copyright (c) by Matthias Hertel, http://www.mathertel.de // This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx // ----- // 03.01.2006 created by Matthias Hertel // 04.01.2006 FireFox compatible. // 25.08.2007 supporting more attributes title, link, img on file nodes. // 26.08.2007 supporting OpenAjax hub events. var TreeViewBehaviour = { /// <summary>Implementation of a JavaScript Behavior for a treeview control. /// This control implements a treeview that is dynamically expanded with sub nodes /// when the user clicks on an existing non-expanded node. /// The new subnodes are retrieved by using a webservice call.</summary> _namespace: "de.mathertel.treeview.", /// <summary>The root namespace for treview events.</summary> // ----- Properties ----- service: "", /// <summary>Name or object reference to the WebService function proxy.</summary> init: function () { /// <summary>Initialize the control.</summary> this.ExploreAction.call = this.service; }, // init // ----- Events ----- onclick: function (evt) { /// <summary>Handle clicks on folder or file lines.</summary> evt = evt || window.event; var t = evt.target || evt.srcElement; if ((t.href != null) && (t.href != "") && (t.href != window.location.href + "#")) { return; // just follow the link } // skip some inner elements without any functionality while ((t != null) && ((t.className == "") || (t.className == "ft"))) t = t.parentNode; // clicked on a file ? if (t.className.substr(0, 2) == "fl") { var path = TreeViewBehaviour._nodePath(t); OpenAjax.hub.publish(this._namespace + "click", path); } // clicked on a folder ? if ((t.className != "do") && (t.className != "dc") && (t.className != "du")) t = t.parentNode; if ((t.className == "do") || (t.className == "dc") || (t.className == "du")) { var subf = t.nextSibling; if ((subf != null) && (subf.nodeName != "DIV")) subf = subf.nextSibling; if ((subf == null) || (subf.nodeName != "DIV")) { // this should never happen } else if (t.className == "do") { // hide subtree t.className = "dc"; subf.style.display = "none"; } else if (t.className == "dc") { // show subtree t.className = "do"; subf.style.display = "block"; } else if (t.className == "du") { // start loading a new subtree fragment t.className = "do"; subf.innerText = "loading..."; subf.style.display = "block"; ajax.Start(this.ExploreAction, t); } } // if // cancle the standard click actions. evt.cancelBubble = true; evt.returnValue = false; }, // onchange 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[@title]'><div class='du'><xsl:attribute name='name'><xsl:value-of select='@name' /></xsl:attribute><span class='ft'><xsl:value-of select='@title' /></span></div><div class='subframe' style='display:none'></div></xsl:template>\ <xsl:template match='folder'><div class='du'><xsl:attribute name='name'><xsl:value-of select='@name' /></xsl:attribute><span class='ft'><xsl:value-of select='@name' /></span></div><div class='subframe' style='display:none'><xsl:apply-templates /></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: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>", /// <summary>The xslt that is used to transfer the retrieved nodes into valid HTML code.</summary> // ----- Methods ----- ExtendTree: function (src, data) { /// <summary>Extend the src node by the given xml structure.</summary> var subf = src.nextSibling; if ((subf != null) && (subf.nodeName != "DIV")) subf = subf.nextSibling; if (window.XSLTProcessor) { // Mozilla... if (typeof (this.xslt) == "string") { this.xslt = ajax._getXMLDOM(this.xslt); } // if // Finally import the .xsl var xsltProcessor = new XSLTProcessor(); xsltProcessor.importStylesheet(this.xslt); var fragment = xsltProcessor.transformToFragment(data, window.document); subf.innerHTML = ""; subf.appendChild(fragment); } else if (window.ActiveXObject || "ActiveXObject" in window) { // load xslt text into a XSLTemplate var xslt = new ActiveXObject("Msxml2.XSLTemplate"); var xsltDoc = new ActiveXObject("Msxml2.FreeThreadedDOMDocument"); xsltDoc.async = false; xsltDoc.loadXML(this.xslt); xslt.stylesheet = xsltDoc; // data + xlst => html var xslProc = xslt.createProcessor(); xslProc.input = data; xslProc.transform(); subf.innerHTML = xslProc.output; } else { // IE if (typeof (this.xslt) == "string") { var xsltDoc = new ActiveXObject("Msxml2.DOMDocument"); xsltDoc.async = false; xsltDoc.loadXML(this.xslt); this.xslt = xsltDoc; } // if subf.innerHTML = data.transformNode(this.xslt); } // if if (subf.childNodes.length == 0) { src.className = "de"; subf.style.display = "none"; } // if }, // ExtendTree _nodePath: function (src) { /// <summary>Build the full path name for a given node.</summary> var path = ""; while ((src != null) && (src._attachedBehaviour != TreeViewBehaviour)) { if (src.nodeType == 3) { src = src.previousSibling; } else if (src.className == "subframe") { src = src.previousSibling; } else if ((src.className == "do") || (src.className.substr(0, 2) == "fl")) { // append the path by the name of this file or folder node. path = "/" + src.attributes["name"].value + path; src = src.parentNode; } else { src = src.parentNode; } // if } while (path.substr(0, 2) == "//") path = path.substr(1); return (path); }, // _nodePath // ----- AJAX Actions ----- ExploreAction: { /// <summary>The ajax action that is used to retrieve the sub-nodes of a given folder.</summary> delay: 10, queueMultiple: true, prepare: function (src) { return (TreeViewBehaviour._nodePath(src)); }, call: "", finish: function (data, src) { jcl.FindBehaviourElement(src, TreeViewBehaviour).ExtendTree(src, data); }, onException: proxies.alertException } // ExploreAction }; // TreeViewBehaviour
This page is part of the http://www.mathertel.de/ web site.
For updates and discussions see http://ajaxaspects.blogspot.com/.