PageRenderTime 43ms CodeModel.GetById 12ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/ddoc/candydoc/explorer.js

http://github.com/baryluk/cords
JavaScript | 305 lines | 225 code | 53 blank | 27 comment | 54 complexity | 383e8c672290e1edf3a1d1dc45c38f44 MD5 | raw file
  1/* This file is a part of CanDyDOC fileset.
  2   File is written by Victor Nakoryakov and placed into the public domain.
  3
  4   This file is javascript with classes that represents explorer window.
  5   And things related to navigation. */
  6   
  7var explorer = new Explorer();
  8
  9///////////////////////////////////////////////////////////////////////////////
 10// Current symbol marker class constructor
 11///////////////////////////////////////////////////////////////////////////////
 12function Marker()
 13{
 14    this.top    = document.createElement("div");
 15    this.middle = document.createElement("div");
 16    this.bottom = document.createElement("div");
 17    this.container = document.createElement("div");
 18    
 19    this.setTo = function(term)
 20    {
 21        // find definition related to `term`
 22        var def = term.nextSibling;
 23        while (def && def.nodeName != "DD")
 24            def = def.nextSibling;
 25            
 26        var defHeight = 0;
 27        var childrenHeight = 0; // children of current declaration
 28        if (def)
 29        {
 30            defHeight = def.offsetHeight;
 31            var child = def.firstChild;
 32            
 33            // traverse until DL tag, until children definition
 34            while (child && child.nodeName != "DL")
 35                child = child.nextSibling;
 36                
 37            if (child)
 38                childrenHeight = child.offsetHeight;
 39        }
 40        
 41        this.top.style.height = term.offsetHeight;
 42        this.middle.style.height = defHeight - childrenHeight;
 43        this.bottom.style.height = childrenHeight;
 44        
 45        if (childrenHeight == 0)
 46            this.bottom.style.display = "none";
 47        else
 48            this.bottom.style.display = "";
 49        
 50        this.container.style.left = getLeft(term) - 8;
 51        this.container.style.top = getTop(term);
 52        this.container.style.display = "";
 53    }
 54        
 55    ///////////////////////////////////////////////////////////////////////////
 56    this.container.style.position = "absolute";
 57    this.container.style.display = "none";
 58    
 59    this.top.className = "markertop";
 60    this.middle.className = "markermiddle";
 61    this.bottom.className = "markerbottom";
 62    
 63    this.container.appendChild(this.top);
 64    this.container.appendChild(this.middle);
 65    this.container.appendChild(this.bottom);
 66    
 67    //document.body.appendChild( this.container );
 68    
 69    // Workaround bug in IE 5/6. We can not append anything to document body until
 70    // full page load.
 71    window.marker = this;
 72    if (window.addEventListener)
 73        window.addEventListener("load", new Function("document.body.appendChild( window.marker.container );"), false);
 74    else if (window.attachEvent)
 75        window.attachEvent("onload", new Function("document.body.appendChild( window.marker.container );"));
 76}
 77
 78///////////////////////////////////////////////////////////////////////////////
 79// Outline class constructor
 80///////////////////////////////////////////////////////////////////////////////
 81function Outline()
 82{
 83    this.tree           = new TreeView();
 84    this.mountPoint     = null;    
 85    this.writeEnabled   = false;
 86    this.marker         = new Marker();        
 87    this.classRegExp    = new RegExp;
 88    this.structRegExp   = new RegExp;
 89    this.enumRegExp     = new RegExp;
 90    this.templateRegExp = new RegExp;
 91    this.aliasRegExp    = new RegExp;
 92    this.funcRegExp     = new RegExp;
 93    
 94    this.incSymbolLevel = function()
 95    {
 96        if (this.mountPoint == null)
 97            this.mountPoint = this.tree.children[ 0 ];
 98        else
 99            this.mountPoint = this.mountPoint.lastChild();
100    }
101
102    this.decSymbolLevel = function()
103    {
104        // place icons near items according to extracted below type
105        for (var i = 0; i < this.mountPoint.children.length; ++i)
106        {
107            child = this.mountPoint.children[i];
108            var term = child.termRef;
109            
110            // find first span node
111            var n = term.firstChild;
112            while (n && n.nodeName != "SPAN")
113                n = n.nextSibling;
114            
115            if (!n) // shouldn't happen
116                continue;
117            
118            var iconSrc;
119            if (n.firstChild.nodeName == "#text")
120            {
121                var text = n.firstChild.data; // text before declaration
122                
123                if ( this.classRegExp.test(text) )
124                    iconSrc = "candydoc/img/outline/class.gif";
125                else if ( this.structRegExp.test(text) )
126                    iconSrc = "candydoc/img/outline/struct.gif";
127                else if ( this.enumRegExp.test(text) )
128                    iconSrc = "candydoc/img/outline/enum.gif";
129                else if ( this.templateRegExp.test(text) )
130                    iconSrc = "candydoc/img/outline/template.gif";
131                else if ( this.aliasRegExp.test(text) )
132                    iconSrc = "candydoc/img/outline/alias.gif";
133                else // function or variable? check whether '(' ')' exists on the right
134                {
135                    var np = n.firstChild;
136                    while (np && np.nodeName != "SCRIPT") // find our script "onDecl"
137                        np = np.nextSibling;
138                        
139                    if (np && np.nextSibling && np.nextSibling.nodeName == "#text" &&
140                        this.funcRegExp.test(np.nextSibling.data))
141                    {
142                        iconSrc = "candydoc/img/outline/func.gif";
143                    }
144                    else
145                        iconSrc = "candydoc/img/outline/var.gif";
146                }
147            }
148            else // enum member ?
149                iconSrc = "candydoc/img/outline/var.gif";
150                    
151            child.icon.src = iconSrc;
152            child.icon.width = 16;
153            child.icon.height = 16;
154        }
155        
156        this.mountPoint = this.mountPoint.parentNode;
157    }
158
159    this.addDecl = function(decl)
160    {
161        function getLastLeaf(elem)
162        {
163            if (elem.childNodes.length > 0)
164                return getLastLeaf(elem.lastChild);
165            else
166                return elem;
167        }
168
169        function getCurrentTerm()
170        {
171            var ret = getLastLeaf( document.getElementById("content") );
172            while (ret && ret.nodeName != "DT")
173                ret = ret.parentNode;
174            
175            return ret;
176        }
177        
178        if (this.writeEnabled)
179        {
180            var node = this.mountPoint.createChild(decl);
181            node.termRef = getCurrentTerm();
182            node.setOnclick( new Function("explorer.outline.mark(this.termRef);") );
183        }
184    }
185
186    this.mark = function(term)
187    {
188        this.marker.setTo(term);
189        window.scrollTo(0, getTop(term) - getWindowHeight() / 6);    
190    }
191        
192    
193    this.classRegExp.compile("(.*\b)?class(\b.*)?");
194    this.structRegExp.compile("(.*\b)?struct(\b.*)?");
195    this.enumRegExp.compile("(.*\b)?enum(\b.*)?");
196    this.templateRegExp.compile("(.*\b)?template(\b.*)?");
197    this.aliasRegExp.compile("(.*\b)?alias(\b.*)?");
198    this.funcRegExp.compile(/.*\(.*/);    
199}
200
201
202
203
204///////////////////////////////////////////////////////////////////////////////
205// Package explorer class constructor
206///////////////////////////////////////////////////////////////////////////////
207function PackageExplorer()
208{
209    this.tree = new TreeView(true);    
210    
211    this.addModule = function(mod)
212    {
213        var moduleIco = "candydoc/img/outline/module.gif";
214        var packageIco = "candydoc/img/outline/package.gif";
215
216        var path = mod.split("\.");
217        var node = this.tree.branch(path[0]);
218        if ( !node )
219            node = this.tree.createBranch(path[0], (path.length == 1) ? moduleIco : packageIco);
220        
221        for (var i = 1; i < path.length; ++i)
222        {
223            var prev = node;
224            node = node.child(path[i]);
225            if (!node)
226                node = prev.createChild(path[i], (path.length == i + 1) ? moduleIco : packageIco);
227                
228            if (path.length == i + 1)
229                node.setRef(path[i] + ".html");
230        }
231    }
232}
233
234
235
236///////////////////////////////////////////////////////////////////////////////
237// Explorer class constructor
238///////////////////////////////////////////////////////////////////////////////
239function Explorer()
240{
241    this.outline         = new Outline();
242    this.packageExplorer = new PackageExplorer();
243    this.tabs            = new Array();
244    this.tabCount        = 0;
245    
246    this.initialize = function(moduleName)
247    {
248        this.tabArea = document.getElementById("tabarea");
249        this.clientArea = document.getElementById("explorerclient");
250        
251        // prevent text selection
252        this.tabArea.onmousedown = new Function("return false;");
253        this.tabArea.onclick = new Function("return true;");
254        this.tabArea.onselectstart = new Function("return false;");
255        this.clientArea.onmousedown = new Function("return false;");
256        this.clientArea.onclick = new Function("return true;");
257        this.clientArea.onselectstart = new Function("return false;");
258        
259        this.outline.tree.createBranch( moduleName, "candydoc/img/outline/module.gif" );
260        
261        // create tabs
262        this.createTab("Outline", this.outline.tree.domEntry);
263        this.createTab("Package", this.packageExplorer.tree.domEntry);
264    }
265    
266    this.createTab = function(name, domEntry)
267    {
268        var tab = new Object();
269        this.tabs[name] = tab;
270        this.tabCount++;
271        
272        tab.domEntry = domEntry;
273        tab.labelSpan = document.createElement("span");
274        
275        if (this.tabCount > 1)
276        {
277            tab.labelSpan.className = "inactivetab";
278            tab.domEntry.style.display = "none";
279        }
280        else
281        {
282            tab.labelSpan.className = "activetab";
283            tab.domEntry.style.display = "";
284        }
285        
286        tab.labelSpan.appendChild( document.createTextNode(name) );
287        tab.labelSpan.owner = this;
288        tab.labelSpan.onclick = new Function("this.owner.setSelection('" + name + "');");
289        
290        this.tabArea.appendChild( tab.labelSpan );
291        this.clientArea.appendChild( domEntry );
292    }
293    
294    this.setSelection = function(tabName)
295    {
296        for (name in this.tabs)
297        {
298            this.tabs[name].labelSpan.className = "inactivetab";
299            this.tabs[name].domEntry.style.display = "none";
300        }
301        
302        this.tabs[tabName].labelSpan.className = "activetab";
303        this.tabs[tabName].domEntry.style.display = "";
304    }
305}