
    //*********************************** Treeview API class *************************************
    var CTreeviewAPI = function(){
        //buttons array
        this.instances = new Array(); //[0] => name ; [1] => object
    }

    CTreeviewAPI.prototype.get_instance = function(name)
    {
        for(var i = 0; i < this.instances.length; i++){
            if(this.instances[i][0] == name) return this.instances[i][1];
        }
        return null;
    }

    CTreeviewAPI.prototype.add_instance = function(name, instance)
    {
        this.instances[this.instances.length] = new Array(name, instance);
    }

    //creating api object
    var TreeviewAPI = new CTreeviewAPI();


    NODESTATE_COLLAPSED = 1;
    NODESTATE_EXPANDED = 2;
    NODETYPE_AUTO = 0;
    NODETYPE_FOLDER = 1;
    NODETYPE_LEAF = 2;


    function treeview_node_ec(){
        node = this.node;
        if(node){
            if(node.is_collapsed())
                node.expand();
            else
                node.collapse();
        }
    }


    var CNode = function(parent, id, caption, href, onclick, inherit){
        this.class_name = 'CNode';
        //setting default values
        var inherit = (inherit == null) ? true : inherit;
        var href = (href == null) ? false : href;
        var onclick = (onclick == null) ? '' : onclick;
        //main properties
        this.id = id;
        this.parent = parent;
        this.caption = caption;
        this.visible = true;
        this.state = NODESTATE_COLLAPSED;
        this.type = NODETYPE_AUTO;
        this.remember_state = true;
        this.href = href;
        this.onclick = onclick;
        this.inherit = inherit;
        //apperance images and classes
        this.fld_img_closed = '';
        this.fld_img_open = '';
        this.fld_class_closed = '';
        this.fld_class_open = '';
        this.leaf_img = '';
        this.leaf_class = '';
        this.childs = new Array();
        this.obj_cnt = document.createElement('div');        //div containing the node and his childs
        this.obj_childscnt = document.createElement('div');  //div containing childs
        this.obj_node = document.createElement('label');       //anchor representing node name
        this.obj_ecimg = document.createElement('img');
        this.obj_nodeimg = document.createElement('img');
        //inheriting properties
        if(this.inherit && this.parent && this.parent.class_name == 'CNode'){
            this.fld_img_closed = this.parent.fld_img_closed;
            this.fld_img_open = this.parent.fld_img_open;
            this.fld_class_closed = this.parent.fld_class_closed;
            this.fld_class_open = this.parent.fld_class_open;
            this.leaf_img = this.parent.leaf_img;
            this.leaf_class = this.parent.leaf_class;
        }
        //saving state
        if(this.remember_state)
            this.restore_state(false);
    }

    //childs procs
    CNode.prototype.add_childobj = function(childobj){
        var length = this.childs.length;
        this.childs[length] = childobj;
        this._childs_changed();
    }

    CNode.prototype.add_child = function(id, caption, href, onclick, inherit){
        var node = new CNode(this, id, caption, href, onclick, inherit);
        this.add_childobj(node);
        this._childs_changed();
        return node;
    }

    CNode.prototype.has_childs = function(){
        return this.childs.length > 0;
    }

    //parent procs
    CNode.prototype.set_parent = function(parent){
        this.parent = parent;
    }

    CNode.prototype.get_parent = function(){
        return this.parent;
    }

    //caption procs
    CNode.prototype.set_caption = function(caption){
        this.caption = caption;
        if(this.obj_node){
            this.obj_node.innerHTML = this.caption;
        }
    }

    CNode.prototype.get_caption = function(){
        return this.caption;
    }

    //visible procs
    CNode.prototype.set_visible = function(visible){
        this.visible = visible;
        this._visible_changed();
    }

    CNode.prototype.get_visible = function(){
        return this.visible;
    }

    //state procs
    CNode.prototype.set_remember_state = function(remember_state, set_recursively){
        this.remember_state = remember_state;
        if(this.remember_state)
            this.save_state(false);
        //setting recursively
        if(set_recursively){
            for(var i = 0; i < this.childs.length; i++){
                this.childs[i].set_remember_state(remember_state, set_recursively);
            }
        }
    }

    CNode.prototype.get_remember_state = function(){
        return this.remember_state;
    }

    CNode.prototype.is_expanded = function(){
        return this.state == NODESTATE_EXPANDED;
    }

    CNode.prototype.is_collapsed = function(){
        return this.state == NODESTATE_COLLAPSED;
    }

    CNode.prototype.collapse = function(){
        this.state = NODESTATE_COLLAPSED;
        this._state_changed();
    }

    CNode.prototype.expand = function(){
        this.state = NODESTATE_EXPANDED;
        this._state_changed();
    }

    //type procs
    CNode.prototype.set_type_folder = function(){
        this.type = NODETYPE_FOLDER;
        this._type_changed();
    }

    CNode.prototype.set_type_leaf = function(){
        this.type = NODETYPE_LEAF;
        this._type_changed();
    }

    CNode.prototype.set_type_auto = function(){
        this.type = NODETYPE_AUTO;
        this._type_changed();
    }

    //href procs
    CNode.prototype.set_href = function(href){
        this.href = href;
        if(this.obj_node){
            this.obj_node.href = this.href;
        }
    }

    CNode.prototype.get_href = function(){
        return this.href;
    }

    //onclick procs
    CNode.prototype.set_onclick = function(onclick){
        this.onclick = onclick;
        if(this.obj_node){
            this.obj_node.onclick = this.onclick;
        }
    }

    CNode.prototype.get_onclick = function(){
        return this.onclick;
    }

    //images & classes procs
    CNode.prototype.set_fld_img = function(closed_url, open_url){
        this.fld_img_closed = closed_url;
        this.fld_img_open = open_url;
    }

    CNode.prototype.set_fld_class = function(closed_classname, open_classname){
        this.fld_class_closed = closed_class;
        this.fld_class_open = open_class;
    }

    CNode.prototype.set_leaf_img = function(url){
        this.leaf_img = url;
    }

    CNode.prototype.set_leaf_class = function(classname){
        this.leaf_class = classname;
    }


    //private procs
    CNode.prototype._state_changed = function(){
        var treeview = this.get_treeview();
        if(this.is_collapsed()){
            this.obj_ecimg.src = treeview.root_url + '/images/expand.gif';
            this.obj_childscnt.style.display = 'none';
        } else {
            this.obj_ecimg.src = treeview.root_url + '/images/collapse.gif';
            this.obj_childscnt.style.display = '';
        }
        //refreshing image
        this._refresh_image();
        //saving state
        if(this.remember_state)
            this.save_state(false);
    }


    CNode.prototype._type_changed = function(){
        //refreshing images
        this._refresh_image();
    }


    CNode.prototype._childs_changed = function(){
        //if node has childs it is a folder
        if(this.has_childs()){
            //setting collapse/expande command image visible
            this.obj_ecimg.style.visibility = 'visible';
        } else {
            //setting collapse/expande command image hidden
            this.obj_ecimg.style.visibility = 'hidden';
        }
        //refreshing images
        this._refresh_image();
    }

    CNode.prototype._visible_changed = function(){
        if(this.visible)
            this.obj_cnt.style.display = '';
        else
            this.obj_cnt.style.display = 'none';
    }

    CNode.prototype._refresh_image = function(){
        if((this.has_childs() && this.type == NODETYPE_AUTO) || this.type == NODETYPE_FOLDER){
            //setting folder image
            if(this.is_collapsed()){
                //setting folder image closed
                if(this.fld_img_closed){
                    this.obj_nodeimg.style.display = '';
                    this.obj_nodeimg.src = this.fld_img_closed;
                } else {
                    this.obj_nodeimg.style.display = 'none';
                }
            } else {
                //setting folder image open
                if(this.fld_img_open){
                    this.obj_nodeimg.style.display = '';
                    this.obj_nodeimg.src = this.fld_img_open;
                } else {
                    this.obj_nodeimg.style.display = 'none';
                }
            }
        }
        if((!this.has_childs() && this.type == NODETYPE_AUTO) || this.type == NODETYPE_LEAF){
            //setting leaf image
            if(this.leaf_img){
                this.obj_nodeimg.style.display = '';
                this.obj_nodeimg.src = this.leaf_img;
            } else {
                this.obj_nodeimg.style.display = 'none';
            }
        }
    }


    //generic procs
    CNode.prototype.get_treeview = function(){
        if(this.parent.class_name == 'CNode'){
            return this.parent.get_treeview();
        }
        if(this.parent.class_name == 'CTreeview'){
            return this.parent;
        }
        return null;
    }

    CNode.prototype.find_node_by_id = function(id){
        for(var i = 0; i < this.childs.length; i++){
            if(this.childs[i].id == id)
                return this.childs[i];
            var node = this.childs[i].find_node_by_id(id);
            if(node)
                return node;
            else
                return null;
        }
    }


    CNode.prototype.rebuild = function()
    {
        //if node is child of anoter
        if(this.parent.class_name == 'CNode'){
            var parent_childs_cnt = this.parent.obj_childscnt;
        }
        //if node is root and parent is CTreeview
        if(this.parent.class_name == 'CTreeview'){
            var parent_childs_cnt = document.getElementById(this.parent.container_id);
        }
        if(!parent_childs_cnt) return;

        var treeview = this.get_treeview();

        //destroying current tree
        this.obj_cnt.innerHTML = '';

        //creating container
        this.obj_cnt.style.padding = '2px 2px 2px 2px';
        this.obj_cnt.align = 'left';
		parent_childs_cnt.appendChild(this.obj_cnt);

        //creating expand/collapse image
        this.obj_ecimg.border = 0;
        this.obj_ecimg.node = this;
        this.obj_ecimg.onclick = treeview_node_ec;
        this.obj_cnt.appendChild(this.obj_ecimg);

        //creating spacer
        var spacer = document.createTextNode(' ');
        this.obj_cnt.appendChild(spacer);

        //creating node image;
        this.obj_nodeimg.border = 0;
        this.obj_nodeimg.align = 'absmiddle';
        this.obj_nodeimg.node = this;
        this.obj_cnt.appendChild(this.obj_nodeimg);

        //creating spacer
        var spacer = document.createTextNode(' ');
        this.obj_cnt.appendChild(spacer);

        //creating anchor
        if(this.href){
            caption = '<a href="' + this.href + '">' + this.caption + '</a>';
        } else {
            caption = this.caption;
        }

        this.obj_node.innerHTML = caption;
        if(this.onclick)
            this.obj_node.onclick = this.onclick;
		this.obj_cnt.appendChild(this.obj_node);

        //creating br
        var br = document.createElement('br');
        this.obj_cnt.appendChild(br);

        //creating child container
        this.obj_childscnt.style.paddingLeft = '20px';
        this.obj_childscnt.align = 'left';
		this.obj_cnt.appendChild(this.obj_childscnt);

        //outputting childs
        for(var i = 0; i < this.childs.length; i++){
            this.childs[i].output();
        }

        this._state_changed();

        this._childs_changed();

        this._type_changed();

    }

    CNode.prototype.output = function()
    {
        this.rebuild();
    }

    CNode.prototype.save_state = function(recursive){
        document.cookie = this.id + '=' + this.state;
        if(recursive){
            for(var i = 0; i < this.childs.length; i++){
                this.childs[i].save_state(recursive);
            }
        }
    }

    CNode.prototype.restore_state = function(recursive){
        cookiestr = document.cookie;
        cookies = cookiestr.split('; ');
        for(var i = 0; i < cookies.length; i++){
            namevalue = String(cookies[i]).split('=');
            if(namevalue[0] == String(this.id)){
                if(Number(namevalue[1]) == NODESTATE_COLLAPSED)
                    this.collapse();
                if(Number(namevalue[1]) == NODESTATE_EXPANDED)
                    this.expand();
            }
        }
        if(recursive){
            for(var i = 0; i < this.childs.length; i++){
                this.childs[i].restore_state(recursive);
            }
        }
    }




    //*********************************** Treeview class *************************************

	var CTreeview = function(instance_name, root_url){
        this.class_name = 'CTreeview';
        //setting main properties
        this.instance_name = instance_name;
        this.root_url = root_url;
        this.container_id = '';
        this.remember_state = true;
        //creating root node
        this.root = new CNode(this, instance_name, 'root');
        //setting initial images
        this.root.set_fld_img(this.root_url + '/images/fld_close.gif', this.root_url + '/images/fld_open.gif');
        this.root.set_leaf_img(this.root_url + '/images/leaf.gif');
        //adding instance to api class
        TreeviewAPI.add_instance(this._instance_name, this);
        this.set_remember_state(true);
    }

    CTreeview.prototype.get_instance_name = function()
    {
        return this.instance_name;
    }

    CTreeview.prototype.set_container_id = function(container_id)
    {
        this.container_id = container_id;
    }

    CTreeview.prototype.set_remember_state = function(remember_state)
    {
        this.remember_state = remember_state;
        this.root.set_remember_state(remember_state, true);
    }

    CTreeview.prototype.get_remember_state = function()
    {
        return this.remember_state;
    }

    CTreeview.prototype.output = function(){
        this.root.output();
    }

    CTreeview.prototype.rebuild = function(){
        this.root.rebuild();
    }

    CTreeview.prototype.find_node_by_id = function(id){
        if(this.root.id = id){
            return this.root;
        } else {
            return this.root.find_node_by_id(id);
        }
    }

    CTreeview.prototype.save_state = function(){
        this.root.save_state(true);
    }

    CTreeview.prototype.restore_state = function(){
        this.root.restore_state(true);
    }


