/* Favorez "My Favorites" JavaScript
 * Copyright (c) 2002 WarpGear Software
 *
 * You are permitted to use this code under the conditions
 * outlined by an M.I.T. style license. According to this
 * license, you may not remove this copyright notice.
 * The complete text of the license can be found here: 
 * http://www.favorez.com/my_favorites_license.txt
 *
 * version: 1.0
 * date: September 5, 2002
 * website: http://favorez-js.sourceforge.net
 * author: Tom Kalmijn
 */

// define globals
var nextId = 0; // counter to obtain unique TreeNode id's
var selId = 0; // id of last clicked link 
var allNodes = new Array; // lookup list for nodes, TreeNode.id equals the position of a node in the list.
var root; // TreeNode: root of all nodes, acts as an anchor for the whole in-memory tree structure.
var indent_strings = new Array;

// Netscape compatibility var
var ns4 = document.layers; // alias for frequently used switch
var ns4_html = ""; // off screen buffer to render html
var ns4_draw = false; // switch for special ns4 drawing

// counteract NS4 infamous resize bug...
var winW = window.innerWidth;
var winH = window.innerHeight;
function onResize() {
    if (ns4) {
        if (winW != window.innerWidth ||
            winH != window.innerHeight) {
            location.reload(true);
        }
    }
}

// declare & define class TreeNode
// *** this class is browser independant, no html allowed ***
function TreeNode(canExpand) {
    this.id = 0;
    this.subNodes = null;
    this.parent = null;
    this.isExpanded = false;
    this.canExpand = canExpand;
    this.visible = false;

    // assign methods (needs to be done only once)
    if (typeof(_TreeNode_prototype_called) == "undefined") {
        _TreeNode_prototype_called = true;
        TreeNode.prototype.expand = expand;
        TreeNode.prototype.add = add;
        TreeNode.prototype.show = show;
        TreeNode.prototype.getIndent = getIndent;
    }

    function add(node) {
        // init subNodes lazily
        if (!this.subNodes) {
            this.subNodes = new Array;
        }
        node.parent = this;
        this.subNodes[this.subNodes.length] = node;
        allNodes[node.id] = node;
    }

    function expand(expand, recurse) {
        if (this.subNodes) {
            var len = this.subNodes.length;
            for (var n = 0; n < len; n++) {
                var node = this.subNodes[n];

                if (node.canExpand && recurse) {
                    node.isExpanded = expand;
                }
                node.show(expand); // JavaScript polymorphism at work!

                if (node.canExpand && (recurse || !expand || node.isExpanded)) {
                    node.expand(expand, recurse);
                }
            }
        }
    }

    function getIndent() {
        if (!this.indent) {
            this.indent = -1;
            var parent = this.parent;
            while (parent) {
                parent = parent.parent;
                this.indent++;
            }
        }
        return this.indent;
    }
    function show() { /* abstract */ alert("error in JavaScript inheritance structure!"); }
}

// Folder extends TreeNode, renders a node as a folder.
// (see prototype assignment at end of class)
function Folder(name) {
    this.id = nextId++; 
    this.name = name;

    // assign methods
    if (typeof(_Folder_prototype_called) == "undefined") {
        _Folder_prototype_called = true;
        Folder.prototype.show = show; // override abstract TreeNode.show
    }

    function show(show) {
        if (this == root) return;

        if (this.visible || show) {
            this.visible = show;
            if (!this.div && !ns4) this.div = getElement(this.id);

            if (show) {
                var html = "";
                if ((!this.html_open && this.isExpanded) || (!this.html_closed && !this.isExpanded)) {
                    html = "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">";
                    html += "<tr nowrap><td height=\"20\" valign=\"bottom\">" + indent_strings[this.getIndent()];
                    html += "<a onClick=\"javascript:void(0);\" href=\"javascript:expand('" + this.id + "');\"><img align=\"absmiddle\" src=\"";
                    html += (this.isExpanded) ? "03.png" : "02.png";
                    html += "\" border=\"0\"></a></td><td width=\"100%\" align=\"left\" >&nbsp;<font size=\"-1\">";
                    html += "<a onClick=\"javascript:void(0);\" href=\"javascript:expand('" + this.id + "');\">" + this.name + "</a></font></td>";
                    html += "</tr></table>";
                    if (this.isExpanded)
                        this.html_open = html;
                    else
                        this.html_closed = html;
                }
                html = this.isExpanded ? this.html_open : this.html_closed;

                if (ns4) { if (ns4_draw) ns4_html += html; }
                else htmlWrite(this.div, html);
            }
            if (!ns4) this.div.style.display = show ? "" : "none";
        }
    }
}
Folder.prototype = new TreeNode(true); 

// Url extends TreeNode, renders a node as an url.
function Url(title, path, icon) {
    this.id = nextId++;
    this.title = title;
    this.path = path;
    this.icon = icon;
    this.selected = false;

    if (typeof(_Url_prototype_called) == "undefined") {
        _Url_prototype_called = true;
        Url.prototype.show = show;
    }

    function show(show) {
        if (this.visible || show) {
            this.visible = show;
            if (!this.div && !ns4) this.div = getElement(this.id);

            var s = (this.id - selId == 0); 
            var redraw = !this.html || (this.selected != s);
            this.selected = s;
                        
            if (show && redraw) {
                this.html = "<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\"><tr nowrap><td height=\"20\" valign=\"bottom\">" + indent_strings[this.getIndent()];
                this.html += "<a onClick=\"select('" + this.id + "')\" href=\"" + this.path + "\" target=\"_blank\">";
                this.html += "<img align=\"absmiddle\" src=\"" + this.icon + "\" alt=\"" + this.path + "\" border=\"0\"></a></td>";
                this.html += "<td nowrap width=\"100%\">&nbsp;<a onClick=\"select('" + this.id + "')\" href=\"" + this.path + "\" target=\"_blank\"><font size=\"-1\">";
                this.html += s ? "<b>" + this.title + "</b>" : this.title;
                this.html += "</font></a></td></tr></table>";
                if (!ns4) htmlWrite(this.div, this.html);                        
            }
            if (ns4) { if (ns4_draw) ns4_html += this.html; }
            else this.div.style.display = show ? "" : "none";
        }
    }
}
Url.prototype = new TreeNode(false);

function updateNode(id) {
    var node = allNodes[id];  
    if (node) node.show(node.visible);
}

// update selection status
function select(id) {
    var prevId = selId;
    selId = id;    

    if (ns4) {
        setTimeout("renderTree()", 200); 
    }
    else { 
        setTimeout("updateNode(" + prevId + ")", 200); 
        setTimeout("updateNode(" + selId + ")", 200);
    }
}

// render whole tree structure (for NS4 only)
function renderTree() {
    ns4_html = ""; // reset buffer to render
    ns4_draw = true;
    show(root);
    ns4_draw = false;
    htmlWrite(document.ns4_tree, ns4_html);
}

function show(node) {
    node.show(true);
    if (node.canExpand) {
        if (node.isExpanded && node.subNodes) {
            var len = node.subNodes.length;
            for (var n = 0; n < len; n++) {
                var subNode = node.subNodes[n];
                show(subNode);
            }
        }
    }
}

function expand(id, recurse) {
    var node = allNodes[id];
    if (node) {
        if (node.canExpand) {
            var expand = !node.isExpanded;
            node.isExpanded = expand;
            node.show(true);
            node.expand(expand, recurse);
            if (ns4) renderTree();
        }
    }
}

function expandAll(doExpand) {
    root.isExpanded = !doExpand;
    expand(root.id, true);
    if (!doExpand) expand(root.id, false); // always expand at least one level
}

// Browser compatibility wrappers...
function htmlWrite(obj, html) {
    if (document.getElementById || document.all) { // IE 4+ & Netscape 6+
        obj.innerHTML = html;
    }
    else if (ns4) { // Netscape 4+
        obj.document.open();
        obj.document.write(html);
        obj.document.close();
    }
}

function getElement(id) {
    if (document.getElementById) { // IE 5+ & Netscape 6+
        return document.getElementById(id);
    }
    else if (document.all) { // IE 4+
        return document.all[id];
    }
    else if (ns4) { // Netscape 4+
        return document[id];
    }
    return null;
}

function setTreePos() {
    if (ns4) {
        var anchor = document.anchors["ns4_tree_anchor"];
        document.ns4_tree.pageX = anchor.x;
        document.ns4_tree.pageY = anchor.y;
        document.ns4_tree.visibility = "visible";
    }   
}       

for (var indent = 0; indent < 16; indent++) {
    var sIndent = "&nbsp;";
    for (var i = 0; i < indent*3; i++) {
        sIndent += "&nbsp;";
    }
    indent_strings[indent] = sIndent;
}

root = new Folder("");
allNodes[0] = root;
