// +---------------------------------------------------------------+
// | DO NOT REMOVE THIS                                            |
// +---------------------------------------------------------------+
// | DynamicTree 1.5.2                                             |
// | Author: Cezary Tomczak [www.gosu.pl]                          |
// | Free for any use as long as all copyright messages are intact |
// +---------------------------------------------------------------+

function DynamicTree(id) {
	 
	 this.foldersAsLinks = false;
	 this.folders_opened = null;
    this.path = "images/";
    this.img = {
        "branch": "blank.gif",
        "doc": "blank.gif",
        "folder": "blank.gif",
        "folderOpen": "blank.gif",
        "leaf": "doc.gif",
        "leafEnd": "doc.gif",
        "node": "fld_closed.gif",
        "nodeEnd": "fld_closed.gif",
        "nodeOpen": "fld_opened.gif",
        "nodeOpenEnd": "fld_opened.gif" };
    this.cookiePath = "";
    this.cookieDomain = "";
    this.init = function() {
        var p, img;
        for (p in this.img) {
            this.img[p] = this.path + this.img[p];
        }
        for (p in this.img) {
            this.imgObjects.push(new Image());
            this.imgObjects.getLast().src = this.img[p];
            this.img[p] = this.imgObjects.getLast().src;
        }
        this.parse(document.getElementById(this.id).childNodes, this.tree, 1);
        this.loadState(this.folders_opened);
        this.updateHtml();
    };
    this.parse = function(nodes, tree) {
        for (var i = 0; i < nodes.length; i++) {
            if (nodes[i].nodeType == 1) {
                if (!nodes[i].className) { continue; }
                if (!nodes[i].id) {
                    nodes[i].id = (++this.count);
	                }
                var node = new Node();
                node.id = nodes[i].id;
                if (nodes[i].firstChild) {
                    if (nodes[i].firstChild.tagName == "A") {
                        var a = nodes[i].firstChild;
                        if (a.firstChild) {
                            node.text = a.firstChild.nodeValue.trim();
                        }
                        if (a.href) {
                            node.href = a.href;
                        }
                        if (a.title) {
                            node.title = a.title;
                        }
                        if (a.target) {
                            node.target = a.target;
                        }
                    } else {                        
                        node.text = nodes[i].firstChild.nodeValue.trim();
                    }
                }
                node.parentNode = tree;
                node.childNodes = (nodes[i].className == "folder" ? new Array() : null);
                node.isDoc      = (nodes[i].className == "doc");
                node.isFolder   = (nodes[i].className == "folder");
                tree.childNodes.push(node);
                
                this.allNodes[node.id] = node;
            }
            if (nodes[i].nodeType == 1 && nodes[i].childNodes) {
                this.parse(nodes[i].childNodes, tree.childNodes.getLast());
            }
        }
    };
	 
    this.nodeClick = function(id) {        		  
		  var el = document.getElementById(id+"-section");
        var node = document.getElementById(id+"-node");
        if (el.style.display == "block") {
            el.style.display = "none";
            if (this.allNodes[id].isLast()) { node.src = this.img.nodeEnd; }
            else { node.src = this.img.node; }
            this.opened.removeByValue(idn);
        } else {
            el.style.display = "block";
            if (this.allNodes[id].isLast()) { node.src = this.img.nodeOpenEnd; }
            else { node.src = this.img.nodeOpen; }
            this.opened.push(id);
        }        
		  /* fix ie bug - images not showing */
        if (node.outerHTML) { node.outerHTML = node.outerHTML; }
    };
	 
    this.textClick = function(id) {
       if (this.active) {
            try {
            	document.getElementById(this.active+"-text").className = "text";
            } catch(E) {}
        }
        document.getElementById(id+"-text").className = "text-active";
        this.active = id;
        this.textClickListener.call();
    };	
	 
    this.toHtml = function() {
        var s = "";
        var nodes = this.tree.childNodes;
        for (var i = 0; i < nodes.length; i++) {
            s += nodes[i].toHtml();
        }
        return s;
    };
	 
    this.updateHtml = function() {
        document.getElementById(this.id).innerHTML = this.toHtml();
    };
	 
    this.loadState = function(opened) {
        if (opened) {
            this.opened = opened.split("_");				
            this.opened.filter(
					function(id) { 
						return self.allNodes[id] && self.allNodes[id].isFolder && self.allNodes[id].childNodes.length;
					}
				);								
        }
    };

// Internet Explorer URL-Encoder
	this.UrlEncode = function(str)  {
	
		var special_chars=[
						[/ä/g	,'%E4'],
						[/Ä/g	,'%D4'],
						[/ü/g	,'%FC'],
						[/Ü/g	,'%DC'],
						[/ö/g	,'%F6'],
						[/Ö/g	,'%D6'],
						[/ß/g	,'%DF']
			];

		for (i=0; i<special_chars.length; i++) {
			str = str.replace(special_chars[i][0], special_chars[i][1]);
		}

		return str; 					// the short way
	}

	function Node(id, text, parentNode, childNodes, isDoc, isFolder) {
        this.id = id;
        this.text = text;
        this.parentNode = parentNode;
        this.childNodes = childNodes;
        this.isDoc = isDoc;
        this.isFolder = isFolder;
        this.href = "";
        this.title = "";
        this.target = "";
        this.isLast = function() {
            if (this.parentNode) {
                return this.parentNode.childNodes.getLast().id == this.id;
            }
            throw "DynamicTree.Node.isLast() failed, this func cannot be called for the root element";
        };

        this.toHtml = function() {
            var s = '<div class="?" id="?">'.format((this.isFolder ? "folder" : "doc"), this.id);
            this.href=self.UrlEncode(this.href);
            if (this.isFolder) {            	
      
                var nodeIcon;
                if (this.childNodes.length) {
                    nodeIcon = (self.opened.contains(this.id) ? (this.isLast() ? self.img.nodeOpenEnd : self.img.nodeOpen) : (this.isLast() ? self.img.nodeEnd : self.img.node));
                } else {
                    nodeIcon = (this.isLast() ? self.img.leafEnd : self.img.leaf);
                }
                
                if (this.childNodes.length) { s += '<a href="javascript:void(0)" onclick="?.nodeClick(\'?\')" title="&ouml;ffnen / schlie&szlig;en">'.format(self.id, this.id); }
                s += '<img id="?-node" src="?" width="14" height="16" alt="" vspace="1">'.format(this.id, nodeIcon);
                if (this.childNodes.length) { s += '</a>'; }
                if (self.foldersAsLinks) {                    
                    textlink= '<a href="?"??>?</a>'.format(this.href, (this.title ? ' title="?"'.format(this.title) : ""), (this.target ? ' target="?"'.format(this.target) : ""), this.text);
             		  s += '<span id="?-text" class="text?" onclick="?.textClick(\'?\')">?</span>'.format(this.id, (self.active == this.id ? '-active' : ''), self.id, this.id, textlink);   						  
                } else {                	
                    textlink= '<a href="?"??>?</a>'.format(this.href, (this.title ? ' title="?"'.format(this.title) : ""), (this.target ? ' target="?"'.format(this.target) : ""), this.text);
           		 	  s += '<span id="?-text" class="text?" onclick="?.nodeClick(\'?\')">?</span>'.format(this.id, (self.active == this.id ? '-active' : ''), self.id, this.id, textlink);   						  
                }
                if (this.childNodes.length) {
                    s += '<div class="section?" id="?-section"'.format((this.isLast() ? " last" : ""), this.id);                    

                    if (self.opened.contains(this.id)) {
                        s += '  style="display: block;"'; }
                    s += '>';
                    for (var i = 0; i < this.childNodes.length; i++) {
                        s += this.childNodes[i].toHtml();
                    }
                    s += '</div>';
                }
            }
            if (this.isDoc) {                
                textlink= '<a href="?"??>?</a>'.format(this.href, (this.title ? ' title="?"'.format(this.title) : ""), (this.target ? ' target="?"'.format(this.target) : ""), this.text);
					 s += '<img src="?" width="14" height="16" alt="" vspace="1">'.format((this.isLast() ? self.img.leafEnd : self.img.leaf));                
                s += '<span id="?-text" class="text?" onclick="?.textClick(\'?\')">?</span>'.format(this.id, (self.active == this.id ? '-active' : ''), self.id, this.id, textlink);
            }
            s += '</div>';
            return s;
        };
    }
    function Listener() {
        this.funcs = [];
        this.add = function(func) {
            this.funcs.push(func);
        };
        this.call = function() {
            for (var i = 0; i < this.funcs.length; i++) {
                this.funcs[i]();
            }
        };
    }
	 
	 var self = this;
    this.id = id;

    this.tree = new Node(this.id, "", null, new Array(), false, true);
    this.allNodes = {}; // id => object
    this.opened = []; // opened folders
    this.active = ""; // active node, text clicked
    this.imgObjects = [];
    this.count = 0;
    this.textClickListener = new Listener(); // other modules also may need to know when user clicks on text	 
}

/* Check whether array contains given string */
if (!Array.prototype.contains) {
    Array.prototype.contains = function(s) {
        for (var i = 0; i < this.length; ++i) {
            if (this[i] === s) { return true; }
        }
        return false;
    };
}

/* Remove elements with such value (mutates) */
if (!Array.prototype.removeByValue) {
    Array.prototype.removeByValue = function(value) {
        var i, indexes = [];
        for (i = 0; i < this.length; ++i) {
            if (this[i] === value) { indexes.push(i); }
        }
        for (i = indexes.length - 1; i >= 0; --i) {
            this.splice(indexes[i], 1);
        }
    };
}

/* Remove elements judged 'false' by the passed function (mutates) */
if (!Array.prototype.filter) {
    Array.prototype.filter = function(func) {
        var i, indexes = [];
        for (i = 0; i < this.length; ++i) {
            if (!func(this[i])) { indexes.push(i); }
        }        
		  for (i = indexes.length - 1; i >= 0; --i) {
            this.splice(indexes[i], 1);
        }
    };
}

/* Get the last element from the array */
if (!Array.prototype.getLast) {
    Array.prototype.getLast = function() {
		  return this[this.length-1];
    };
}

/* Strip whitespace from the beginning and end of a string */
if (!String.prototype.trim) {
    String.prototype.trim = function() {
        return this.replace(/^\s*|\s*$/g, "");
    };
}

/* Replace ? tokens with variables passed as arguments in a string */
String.prototype.format = function() {
    if (!arguments.length) { throw "String.format() failed, no arguments passed, this = "+this; }
    var tokens = this.split("?");
    if (arguments.length != (tokens.length - 1)) { throw "String.format() failed, tokens != arguments, this = "+this; }
    var s = tokens[0];
    for (var i = 0; i < arguments.length; ++i) {
        s += (arguments[i] + tokens[i + 1]);
    }
    return s;
};