306 lines
10 KiB
JavaScript
306 lines
10 KiB
JavaScript
|
/* 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 explorer window.
|
||
|
And things related to navigation. */
|
||
|
|
||
|
var explorer = new Explorer();
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Current symbol marker class constructor
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
function Marker()
|
||
|
{
|
||
|
this.top = document.createElement("div");
|
||
|
this.middle = document.createElement("div");
|
||
|
this.bottom = document.createElement("div");
|
||
|
this.container = document.createElement("div");
|
||
|
|
||
|
this.setTo = function(term)
|
||
|
{
|
||
|
// find definition related to `term`
|
||
|
var def = term.nextSibling;
|
||
|
while (def && def.nodeName != "DD")
|
||
|
def = def.nextSibling;
|
||
|
|
||
|
var defHeight = 0;
|
||
|
var childrenHeight = 0; // children of current declaration
|
||
|
if (def)
|
||
|
{
|
||
|
defHeight = def.offsetHeight;
|
||
|
var child = def.firstChild;
|
||
|
|
||
|
// traverse until DL tag, until children definition
|
||
|
while (child && child.nodeName != "DL")
|
||
|
child = child.nextSibling;
|
||
|
|
||
|
if (child)
|
||
|
childrenHeight = child.offsetHeight;
|
||
|
}
|
||
|
|
||
|
this.top.style.height = term.offsetHeight;
|
||
|
this.middle.style.height = defHeight - childrenHeight;
|
||
|
this.bottom.style.height = childrenHeight;
|
||
|
|
||
|
if (childrenHeight == 0)
|
||
|
this.bottom.style.display = "none";
|
||
|
else
|
||
|
this.bottom.style.display = "";
|
||
|
|
||
|
this.container.style.left = getLeft(term) - 8;
|
||
|
this.container.style.top = getTop(term);
|
||
|
this.container.style.display = "";
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
this.container.style.position = "absolute";
|
||
|
this.container.style.display = "none";
|
||
|
|
||
|
this.top.className = "markertop";
|
||
|
this.middle.className = "markermiddle";
|
||
|
this.bottom.className = "markerbottom";
|
||
|
|
||
|
this.container.appendChild(this.top);
|
||
|
this.container.appendChild(this.middle);
|
||
|
this.container.appendChild(this.bottom);
|
||
|
|
||
|
//document.body.appendChild( this.container );
|
||
|
|
||
|
// Workaround bug in IE 5/6. We can not append anything to document body until
|
||
|
// full page load.
|
||
|
window.marker = this;
|
||
|
if (window.addEventListener)
|
||
|
window.addEventListener("load", new Function("document.body.appendChild( window.marker.container );"), false);
|
||
|
else if (window.attachEvent)
|
||
|
window.attachEvent("onload", new Function("document.body.appendChild( window.marker.container );"));
|
||
|
}
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Outline class constructor
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
function Outline()
|
||
|
{
|
||
|
this.tree = new TreeView();
|
||
|
this.mountPoint = null;
|
||
|
this.writeEnabled = false;
|
||
|
this.marker = new Marker();
|
||
|
this.classRegExp = new RegExp;
|
||
|
this.structRegExp = new RegExp;
|
||
|
this.enumRegExp = new RegExp;
|
||
|
this.templateRegExp = new RegExp;
|
||
|
this.aliasRegExp = new RegExp;
|
||
|
this.funcRegExp = new RegExp;
|
||
|
|
||
|
this.incSymbolLevel = function()
|
||
|
{
|
||
|
if (this.mountPoint == null)
|
||
|
this.mountPoint = this.tree.children[ 0 ];
|
||
|
else
|
||
|
this.mountPoint = this.mountPoint.lastChild();
|
||
|
}
|
||
|
|
||
|
this.decSymbolLevel = function()
|
||
|
{
|
||
|
// place icons near items according to extracted below type
|
||
|
for (var i = 0; i < this.mountPoint.children.length; ++i)
|
||
|
{
|
||
|
child = this.mountPoint.children[i];
|
||
|
var term = child.termRef;
|
||
|
|
||
|
// find first span node
|
||
|
var n = term.firstChild;
|
||
|
while (n && n.nodeName != "SPAN")
|
||
|
n = n.nextSibling;
|
||
|
|
||
|
if (!n) // shouldn't happen
|
||
|
continue;
|
||
|
|
||
|
var iconSrc;
|
||
|
if (n.firstChild.nodeName == "#text")
|
||
|
{
|
||
|
var text = n.firstChild.data; // text before declaration
|
||
|
|
||
|
if ( this.classRegExp.test(text) )
|
||
|
iconSrc = "candydoc/img/outline/class.gif";
|
||
|
else if ( this.structRegExp.test(text) )
|
||
|
iconSrc = "candydoc/img/outline/struct.gif";
|
||
|
else if ( this.enumRegExp.test(text) )
|
||
|
iconSrc = "candydoc/img/outline/enum.gif";
|
||
|
else if ( this.templateRegExp.test(text) )
|
||
|
iconSrc = "candydoc/img/outline/template.gif";
|
||
|
else if ( this.aliasRegExp.test(text) )
|
||
|
iconSrc = "candydoc/img/outline/alias.gif";
|
||
|
else // function or variable? check whether '(' ')' exists on the right
|
||
|
{
|
||
|
var np = n.firstChild;
|
||
|
while (np && np.nodeName != "SCRIPT") // find our script "onDecl"
|
||
|
np = np.nextSibling;
|
||
|
|
||
|
if (np && np.nextSibling && np.nextSibling.nodeName == "#text" &&
|
||
|
this.funcRegExp.test(np.nextSibling.data))
|
||
|
{
|
||
|
iconSrc = "candydoc/img/outline/func.gif";
|
||
|
}
|
||
|
else
|
||
|
iconSrc = "candydoc/img/outline/var.gif";
|
||
|
}
|
||
|
}
|
||
|
else // enum member ?
|
||
|
iconSrc = "candydoc/img/outline/var.gif";
|
||
|
|
||
|
child.icon.src = iconSrc;
|
||
|
child.icon.width = 16;
|
||
|
child.icon.height = 16;
|
||
|
}
|
||
|
|
||
|
this.mountPoint = this.mountPoint.parentNode;
|
||
|
}
|
||
|
|
||
|
this.addDecl = function(decl)
|
||
|
{
|
||
|
function getLastLeaf(elem)
|
||
|
{
|
||
|
if (elem.childNodes.length > 0)
|
||
|
return getLastLeaf(elem.lastChild);
|
||
|
else
|
||
|
return elem;
|
||
|
}
|
||
|
|
||
|
function getCurrentTerm()
|
||
|
{
|
||
|
var ret = getLastLeaf( document.getElementById("content") );
|
||
|
while (ret && ret.nodeName != "DT")
|
||
|
ret = ret.parentNode;
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
if (this.writeEnabled)
|
||
|
{
|
||
|
var node = this.mountPoint.createChild(decl);
|
||
|
node.termRef = getCurrentTerm();
|
||
|
node.setOnclick( new Function("explorer.outline.mark(this.termRef);") );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this.mark = function(term)
|
||
|
{
|
||
|
this.marker.setTo(term);
|
||
|
window.scrollTo(0, getTop(term) - getWindowHeight() / 6);
|
||
|
}
|
||
|
|
||
|
|
||
|
this.classRegExp.compile("(.*\b)?class(\b.*)?");
|
||
|
this.structRegExp.compile("(.*\b)?struct(\b.*)?");
|
||
|
this.enumRegExp.compile("(.*\b)?enum(\b.*)?");
|
||
|
this.templateRegExp.compile("(.*\b)?template(\b.*)?");
|
||
|
this.aliasRegExp.compile("(.*\b)?alias(\b.*)?");
|
||
|
this.funcRegExp.compile(/.*\(.*/);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Package explorer class constructor
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
function PackageExplorer()
|
||
|
{
|
||
|
this.tree = new TreeView(true);
|
||
|
|
||
|
this.addModule = function(mod)
|
||
|
{
|
||
|
var moduleIco = "candydoc/img/outline/module.gif";
|
||
|
var packageIco = "candydoc/img/outline/package.gif";
|
||
|
|
||
|
var path = mod.split("\.");
|
||
|
var node = this.tree.branch(path[0]);
|
||
|
if ( !node )
|
||
|
node = this.tree.createBranch(path[0], (path.length == 1) ? moduleIco : packageIco);
|
||
|
|
||
|
for (var i = 1; i < path.length; ++i)
|
||
|
{
|
||
|
var prev = node;
|
||
|
node = node.child(path[i]);
|
||
|
if (!node)
|
||
|
node = prev.createChild(path[i], (path.length == i + 1) ? moduleIco : packageIco);
|
||
|
|
||
|
if (path.length == i + 1)
|
||
|
node.setRef(path[i] + ".html");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
// Explorer class constructor
|
||
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
function Explorer()
|
||
|
{
|
||
|
this.outline = new Outline();
|
||
|
this.packageExplorer = new PackageExplorer();
|
||
|
this.tabs = new Array();
|
||
|
this.tabCount = 0;
|
||
|
|
||
|
this.initialize = function(moduleName)
|
||
|
{
|
||
|
this.tabArea = document.getElementById("tabarea");
|
||
|
this.clientArea = document.getElementById("explorerclient");
|
||
|
|
||
|
// prevent text selection
|
||
|
this.tabArea.onmousedown = new Function("return false;");
|
||
|
this.tabArea.onclick = new Function("return true;");
|
||
|
this.tabArea.onselectstart = new Function("return false;");
|
||
|
this.clientArea.onmousedown = new Function("return false;");
|
||
|
this.clientArea.onclick = new Function("return true;");
|
||
|
this.clientArea.onselectstart = new Function("return false;");
|
||
|
|
||
|
this.outline.tree.createBranch( moduleName, "candydoc/img/outline/module.gif" );
|
||
|
|
||
|
// create tabs
|
||
|
this.createTab("Outline", this.outline.tree.domEntry);
|
||
|
this.createTab("Package", this.packageExplorer.tree.domEntry);
|
||
|
}
|
||
|
|
||
|
this.createTab = function(name, domEntry)
|
||
|
{
|
||
|
var tab = new Object();
|
||
|
this.tabs[name] = tab;
|
||
|
this.tabCount++;
|
||
|
|
||
|
tab.domEntry = domEntry;
|
||
|
tab.labelSpan = document.createElement("span");
|
||
|
|
||
|
if (this.tabCount > 1)
|
||
|
{
|
||
|
tab.labelSpan.className = "inactivetab";
|
||
|
tab.domEntry.style.display = "none";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
tab.labelSpan.className = "activetab";
|
||
|
tab.domEntry.style.display = "";
|
||
|
}
|
||
|
|
||
|
tab.labelSpan.appendChild( document.createTextNode(name) );
|
||
|
tab.labelSpan.owner = this;
|
||
|
tab.labelSpan.onclick = new Function("this.owner.setSelection('" + name + "');");
|
||
|
|
||
|
this.tabArea.appendChild( tab.labelSpan );
|
||
|
this.clientArea.appendChild( domEntry );
|
||
|
}
|
||
|
|
||
|
this.setSelection = function(tabName)
|
||
|
{
|
||
|
for (name in this.tabs)
|
||
|
{
|
||
|
this.tabs[name].labelSpan.className = "inactivetab";
|
||
|
this.tabs[name].domEntry.style.display = "none";
|
||
|
}
|
||
|
|
||
|
this.tabs[tabName].labelSpan.className = "activetab";
|
||
|
this.tabs[tabName].domEntry.style.display = "";
|
||
|
}
|
||
|
}
|