diff docs/candydoc/tree.js @ 206:d3c148ca429b

Major moving of files. all src now goes into src, all docs in docs.
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 18:14:56 +0200
parents doc/candydoc/tree.js@4c121c2aa844
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/candydoc/tree.js	Tue Aug 12 18:14:56 2008 +0200
@@ -0,0 +1,374 @@
+/* This file is a part of CanDyDOC fileset.
+   File is written by Victor Nakoryakov and placed into the public domain.
+
+   This file is javascript with classes that represents native style tree control. */
+   
+var pmNone = 0;
+var pmPlus = 1;
+var pmMinus = 2;
+
+var hlNone = 0;
+var hlGrey = 1;
+var hlSelected = 2;
+
+function TreeView(hrefMode)
+{
+    this.domEntry = document.createElement("div");
+    this.children = new Array();
+    this.selection = null;
+    this.hrefMode = hrefMode;
+    
+    this.createBranch = function(text, iconSrc)
+    {
+        var root = new TreeNode(text, iconSrc, this.hrefMode);
+        root.owner = this;
+        this.children[ this.children.length ] = root;
+        this.domEntry.appendChild( root.domEntry );
+        return root;
+    }
+    
+    this.branch = function(text)
+    {
+        var ret = null;
+        for (var i = 0; i < this.children.length; ++i)
+            if (this.children[i].textElement.data == text)
+            {
+                ret = this.children[i];
+                break;
+            }
+            
+        return ret;
+    }
+    
+    this.domEntry.style.fontSize = "10px";
+    this.domEntry.style.cursor = "default";
+    this.domEntry.style.whiteSpace = "nowrap";
+}
+
+var idCounter = 0;
+function TreeNode(text, iconSrc, hrefMode)
+{
+    this.id             = idCounter++;
+    this.parentNode     = null;
+    this.children       = new Array();
+    this.domEntry       = document.createElement("div");
+    this.icon           = document.createElement("img");
+    this.textElement    = document.createTextNode(text);
+    this.textSpan       = document.createElement("span");
+    this.lineDiv        = document.createElement("div");
+    this.hierarchyImgs  = new Array();
+    this.onclick        = null;
+    
+    function createIcon()
+    {
+        var img = document.createElement("img");
+        img.style.verticalAlign = "middle";
+        img.style.position = "relative";
+        img.style.top = "-1px";
+        img.width = 16;
+        img.height = 16;
+        return img;
+    }
+    
+    function createHierarchyImage()
+    {
+        var img = createIcon();
+        img.pointsTop = false;
+        img.pointsBottom = false;
+        img.pointsRight = false;
+        img.pmState = pmNone;
+        return img;
+    }
+    
+    function genHierarchyImageSrc(hierarchyImg)
+    {
+        var name = "";
+        if (hierarchyImg.pointsTop)
+            name += "t";
+            
+        if (hierarchyImg.pointsBottom)
+            name += "b";
+            
+        if (hierarchyImg.pointsRight)
+            name += "r";
+            
+        if (hierarchyImg.pmState == pmPlus)
+            name += "p";
+        else if (hierarchyImg.pmState == pmMinus)
+            name += "m";
+        
+        if (name == "")
+            name = "shim";
+        
+        return "candydoc/img/tree/" + name + ".gif";
+    }
+    
+    function setSrc(icon, src)
+    {
+        icon.src = src;
+        // After src change width and height are reseted in IE.
+        // Bug workaround:
+        icon.width = 16;
+        icon.height = 16;
+    }
+    
+    this.createChild = function(text, iconSrc)
+    {
+        var child = new TreeNode(text, iconSrc, this.owner.hrefMode);
+        this.children[ this.children.length ] = child;
+        this.domEntry.appendChild( child.domEntry );
+        child.parentNode = this;
+        child.owner = this.owner;
+        
+        // insert hierarchy images according to deepness level
+        // of created child.
+        
+        if (this.children.length > 1)
+        {
+            // there were already added child before. So copy `level-1`
+            // hierarchy images from it.
+            
+            var prevAddedChild = this.children[ this.children.length - 2 ];
+            
+            for (var i = 0; i < prevAddedChild.hierarchyImgs.length - 1; ++i)
+            {
+                var prevAddedChildImg = prevAddedChild.hierarchyImgs[i];
+                var img = createHierarchyImage();
+                setSrc(img, prevAddedChildImg.src);
+                img.pointsTop = prevAddedChildImg.pointsTop;
+                img.pointsBottom = prevAddedChildImg.pointsBottom;
+                img.pointsRight = prevAddedChildImg.pointsRight;
+                img.pmState = prevAddedChildImg.pmState;
+                
+                child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
+                child.lineDiv.insertBefore(img, child.icon);
+            }
+            
+            // change last hierarchy image of prevAddedChild from |_ to |-
+            var lastHierarchyImg = prevAddedChild.hierarchyImgs[ prevAddedChild.hierarchyImgs.length - 1 ];
+            lastHierarchyImg.pointsBottom = true;
+            setSrc(lastHierarchyImg, genHierarchyImageSrc(lastHierarchyImg));
+                        
+            // change hierarchy images of prevAddedChild's children on it's last
+            // level to |
+            prevAddedChild.addHierarchyTBLine(prevAddedChild.hierarchyImgs.length - 1);
+        }
+        else
+        {
+            // this is a first child. So copy `level-2`
+            // hierarchy images from parent, i.e. this.
+            
+            for (var i = 0; i < this.hierarchyImgs.length - 1; ++i)
+            {
+                var parentImg = this.hierarchyImgs[i];
+                var img = createHierarchyImage();
+                setSrc(img, parentImg.src);
+                img.pointsTop = parentImg.pointsTop;
+                img.pointsBottom = parentImg.pointsBottom;
+                img.pointsRight = parentImg.pointsRight;
+                img.pmState = parentImg.pmState;
+                
+                child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
+                child.lineDiv.insertBefore(img, child.icon);
+            }
+            
+            if (this.hierarchyImgs.length > 0) // we are not root
+            {
+                // change last hierarchy image of parent (i.e. this): add minus to it
+                var lastHierarchyImg = this.hierarchyImgs[ this.hierarchyImgs.length - 1];
+                lastHierarchyImg.pmState = pmMinus;
+                setSrc(lastHierarchyImg, genHierarchyImageSrc(lastHierarchyImg));
+                lastHierarchyImg.owner = this;
+                lastHierarchyImg.onclick = new Function("e", "this.owner.processPMClick(e);");
+                
+                // make decision on image on `level-1`. It depends on parent's (ie this)
+                // image on same level.
+                var parentL1HierarchyImg = lastHierarchyImg;
+                var l1HierarchyImg = createHierarchyImage();
+                if (parentL1HierarchyImg.pointsBottom)
+                {
+                    l1HierarchyImg.pointsTop = true;
+                    l1HierarchyImg.pointsBottom = true;
+                }
+                setSrc(l1HierarchyImg, genHierarchyImageSrc(l1HierarchyImg));
+                child.hierarchyImgs[ child.hierarchyImgs.length ] = l1HierarchyImg;
+                child.lineDiv.insertBefore(l1HierarchyImg, child.icon);
+            }
+        }
+        
+        // in any case on last level our child will have icon |_
+        var img = createHierarchyImage();
+        img.pointsTop = true;
+        img.pointsRight = true;
+        setSrc(img, genHierarchyImageSrc(img));
+        
+        child.hierarchyImgs[ child.hierarchyImgs.length ] = img;
+        child.lineDiv.insertBefore(img, child.icon);
+        
+        return child;
+    }
+    
+    this.lastChild = function()
+    {
+        return this.children[ this.children.length - 1 ];
+    }
+    
+    this.child = function(text)
+    {
+        var ret = null;
+        for (var i = 0; i < this.children.length; ++i)
+            if (this.children[i].textElement.data == text)
+            {
+                ret = this.children[i];
+                break;
+            }
+            
+        return ret;
+    }
+    
+    this.addHierarchyTBLine = function(level)
+    {
+        for (var i = 0; i < this.children.length; ++i)
+        {
+            var img = this.children[i].hierarchyImgs[level];
+            img.pointsTop = true;
+            img.pointsBottom = true;
+            setSrc(img, genHierarchyImageSrc(img));
+            this.children[i].addHierarchyTBLine(level);
+        }
+    }
+    
+    this.expand = function()
+    {
+        var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
+        
+        if (img.pmState == pmPlus)
+        {
+            img.pmState = pmMinus;
+            setSrc(img, genHierarchyImageSrc(img));
+            
+            for (var i = 0; i < this.children.length; ++i)
+                this.children[i].domEntry.style.display = "";
+        }
+    }
+    
+    this.collapse = function()
+    {
+        var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
+        
+        if (img.pmState == pmMinus)
+        {
+            img.pmState = pmPlus;
+            setSrc(img, genHierarchyImageSrc(img));
+            
+            for (var i = 0; i < this.children.length; ++i)
+                this.children[i].domEntry.style.display = "none";
+        }
+    }
+    
+    this.toggle = function()
+    {
+        var img = this.hierarchyImgs[ this.hierarchyImgs.length - 1 ];
+        if (img.pmState == pmMinus)
+            this.collapse();
+        else
+            this.expand();
+    }
+    
+    this.select = function()
+    {
+        if (this.owner.selection != this)
+        {
+            if (this.owner.selection)
+                this.owner.selection.setHighlight(hlNone);
+                
+            this.owner.selection = this;
+            this.setHighlight(hlSelected);
+        }
+    }
+    
+    this.setHighlight = function(mode)
+    {
+        if (mode == hlNone)
+        {
+            this.textSpan.style.backgroundColor = "";
+            this.textSpan.style.color = "";
+            this.textSpan.style.border = "";
+        }
+        else if (mode == hlGrey)
+        {
+            this.textSpan.style.backgroundColor = "#aaaaaa";
+            this.textSpan.style.color = "";
+            this.textSpan.style.border = "";
+        }
+        else if (mode == hlSelected)
+        {
+            this.textSpan.style.backgroundColor = "3399cc";
+            this.textSpan.style.color = "white";
+            this.textSpan.style.border = "dotted 1px red";
+        }
+    }
+    
+    this.setOnclick = function(proc)
+    {
+        this.onclick = proc;
+    }
+    
+    this.setRef = function(url)
+    {
+        if (this.anchor)
+            this.anchor.href = url;
+    }
+    
+    this.processPMClick = function(e)
+    {
+        this.toggle();
+        
+        // prevent this line selection, stop bubbling
+        if (e)
+            e.stopPropagation(); // Mozilla way
+        if (window.event)
+            window.event.cancelBubble = true; // IE way
+    }
+    
+    this.processOnclick = function()
+    {
+        this.select();
+        if (this.onclick instanceof Function)
+            this.onclick();
+    }
+    
+    ///////////////////////////////////////////////////////////////////////////
+    if (iconSrc)
+        this.icon.src = iconSrc;
+    else
+    {
+        this.icon.width = 0;
+        this.icon.height = 0;
+    }
+    
+    this.icon.style.verticalAlign = "middle";
+    this.icon.style.position = "relative";
+    this.icon.style.top = "-1px";
+    this.icon.style.paddingRight = "2px";
+    
+    if (!hrefMode)
+    {
+        this.textSpan.appendChild( this.textElement );
+    }
+    else
+    {
+        this.anchor = document.createElement("a");
+        this.anchor.appendChild( this.textElement );
+        this.textSpan.appendChild( this.anchor );
+    }
+    
+    this.lineDiv.appendChild( this.icon );
+    this.lineDiv.appendChild( this.textSpan );
+    this.domEntry.appendChild( this.lineDiv );
+    
+    this.lineDiv.owner = this;
+    
+    if (!hrefMode)
+        this.lineDiv.onclick = new Function("this.owner.processOnclick();");
+}