428 lines
13 KiB
JavaScript
428 lines
13 KiB
JavaScript
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
|
|
// (C) Copyright 2003-2007 Jonathan Turkanis
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
|
|
|
|
//--------------Event-handlers------------------------------------------------//
|
|
|
|
function toggle(id) { get_tree().find(id).toggle(); }
|
|
function blur_tree()
|
|
{
|
|
if ( window.event &&
|
|
window.event.srcElement &&
|
|
window.event.srcElement.blur &&
|
|
window.event.srcElement != document.body )
|
|
window.event.srcElement.blur();
|
|
else if (target_frame())
|
|
target_frame().window.focus();
|
|
}
|
|
document.onclick = blur_tree;
|
|
|
|
//--------------Netscape 4.x-specific-----------------------------------------//
|
|
|
|
window.saved_width = window.outerWidth;
|
|
function reload_tree()
|
|
{
|
|
if (window.outerWidth != window.saved_width)
|
|
window.location.reload();
|
|
}
|
|
if (window.Event && Event.RESIZE) {
|
|
window.captureEvents(Event.RESIZE);
|
|
window.onResize = reload_tree;
|
|
}
|
|
|
|
//--------------Functions for browser-sniffing--------------------------------//
|
|
|
|
function major_version(app)
|
|
{
|
|
var index = navigator.userAgent.indexOf(app);
|
|
if (index == -1)
|
|
return -1;
|
|
return parseInt(navigator.userAgent.charAt(index + app.length + 1));
|
|
}
|
|
function dom_support()
|
|
{
|
|
if (dom_support.cache == null)
|
|
dom_support.cache = dom_support_impl();
|
|
return dom_support.cache;
|
|
}
|
|
function dom_support_impl()
|
|
{
|
|
var version;
|
|
if ( (version = major_version("Mozilla")) != -1 &&
|
|
navigator.userAgent.indexOf("compatible") == -1 )
|
|
return version > 4;
|
|
if ((version = major_version("Opera")) != -1)
|
|
return version > 6;
|
|
if ((version = major_version("Konqueror")) != -1)
|
|
return version > 2;
|
|
if ((version = major_version("Links")) != -1)
|
|
return false;
|
|
return document.getElementById || document.all;
|
|
}
|
|
|
|
//--------------Utility functions---------------------------------------------//
|
|
|
|
function target_frame()
|
|
{
|
|
return get_tree() ? top.frames[get_tree().target] : null;
|
|
}
|
|
function get_tree() { return document.tree_control; }
|
|
function static_display() { return !dom_support() || get_tree().dump_html; }
|
|
function elt_by_id(id)
|
|
{
|
|
return document.all ?
|
|
document.all[id] :
|
|
document.getElementById ?
|
|
document.getElementById(id) :
|
|
null;
|
|
}
|
|
function replace_query(url, query)
|
|
{
|
|
var pos;
|
|
if ((pos = url.indexOf("?")) != -1)
|
|
url = url.substring(0, pos);
|
|
return url + "?" + query;
|
|
}
|
|
|
|
//--------------Functions for HTML-generation---------------------------------//
|
|
|
|
function icon_char(state)
|
|
{
|
|
return state == tree_node.expanded ?
|
|
"-" :
|
|
state == tree_node.collapsed ?
|
|
"+" :
|
|
" ";
|
|
}
|
|
function html_list(id, display, margin)
|
|
{
|
|
return "<div id='" + id + "' style='white-space:nowrap;display:" +
|
|
display + "'>";
|
|
}
|
|
function html_list_item(content)
|
|
{
|
|
return "\n<div class='tree-item'>" + content + "</div>";
|
|
}
|
|
function html_anchor(content, cl, href, target)
|
|
{
|
|
return "<a class='" + cl + "' onfocus='blur_tree()" +
|
|
"' href='" + href + "'" +
|
|
(target ? " target='" + target + "'" : "") +
|
|
">" + content + "</a>";
|
|
}
|
|
|
|
//--------------Definition of class tree_node---------------------------------//
|
|
|
|
function tree_node__add(text_or_node, link_or_hide, hide)
|
|
{
|
|
if (this.state == tree_node.neutral)
|
|
this.state = tree_node.collapsed;
|
|
var k;
|
|
if (text_or_node.length != null) {
|
|
k = new tree_node(text_or_node, link_or_hide);
|
|
k.hide_kids = hide != null ? hide : false;
|
|
} else {
|
|
k = text_or_node;
|
|
k.hide_kids = link_or_hide != null ? link_or_hide : false;
|
|
}
|
|
k.mom = this;
|
|
if (this.kids == null)
|
|
this.kids = new Array();
|
|
this.kids[this.kids.length] = k;
|
|
return k;
|
|
}
|
|
function tree_node__level()
|
|
{
|
|
var level;
|
|
var node;
|
|
for (node = this.mom, level = -1; node; node = node.mom, ++level)
|
|
;
|
|
return level;
|
|
}
|
|
function tree_node__parent() { return this.mom; }
|
|
function tree_node__print()
|
|
{
|
|
var icon =
|
|
!static_display() ?
|
|
"<span style='font-family:monospace' class='tree-icon' id='icon" +
|
|
this.id + "'>" + icon_char(this.state) + "</span> " :
|
|
"";
|
|
var handler =
|
|
!static_display() && this.kids ?
|
|
"javascript:toggle(\"id" + this.id + "\")" :
|
|
"";
|
|
var text = "<span class='tree-text'>" + this.text + "</span>"
|
|
var tree = get_tree();
|
|
var indent = tree.indent * this.level();
|
|
return html_list_item(
|
|
"<div style='margin-left:" + (2 * indent) +
|
|
";text-indent:-" + indent + "'>" +
|
|
( !tree.dump_html ?
|
|
this.kids ?
|
|
html_anchor(icon, "tree-icon", handler) :
|
|
icon :
|
|
"" ) +
|
|
( tree.numbered ?
|
|
"" + "<span class='tree-label'>" +
|
|
this.id.substring(1) + "</span>" :
|
|
"" ) +
|
|
" " +
|
|
( this.link ?
|
|
html_anchor( text, "tree-text", this.link,
|
|
tree.target ) :
|
|
text ) +
|
|
"</div>" +
|
|
this.print_kids()
|
|
);
|
|
}
|
|
function tree_node__print_kids(margin)
|
|
{
|
|
var result = "";
|
|
if (this.kids != null && (!static_display() || !this.hide_kids)) {
|
|
if (margin == null)
|
|
margin = get_tree().indent;
|
|
result += html_list( "list" + this.id,
|
|
this.state == tree_node.collapsed &&
|
|
!static_display()
|
|
? "none" : "",
|
|
margin );
|
|
for (var z = 0; z < this.kids.length; ++z) {
|
|
var k = this.kids[z];
|
|
k.id = this.id + "." + (z + 1);
|
|
result += k.print();
|
|
}
|
|
result += "</div>";
|
|
}
|
|
return result;
|
|
}
|
|
function tree_node__toggle(expand)
|
|
{
|
|
if ( static_display() ||
|
|
this.kids == null ||
|
|
expand != null && expand ==
|
|
(this.state == tree_node.expanded) )
|
|
{
|
|
return;
|
|
}
|
|
this.state =
|
|
this.state == tree_node.expanded ?
|
|
tree_node.collapsed :
|
|
tree_node.expanded;
|
|
elt_by_id("icon" + this.id).innerHTML =
|
|
icon_char(this.state);
|
|
elt_by_id("list" + this.id).style.display =
|
|
this.state == tree_node.expanded ?
|
|
"" :
|
|
"none";
|
|
}
|
|
function add_methods(obj)
|
|
{
|
|
obj.add = tree_node__add;
|
|
obj.level = tree_node__level;
|
|
obj.parent = tree_node__parent;
|
|
obj.print = tree_node__print;
|
|
obj.print_kids = tree_node__print_kids;
|
|
obj.toggle = tree_node__toggle;
|
|
}
|
|
function tree_node(text, link)
|
|
{
|
|
// Member data
|
|
this.text = text;
|
|
this.link = link;
|
|
this.mom = null;
|
|
this.kids = null;
|
|
this.id = null;
|
|
this.state = 0; // Neutral.
|
|
|
|
if (!add_methods.prototype)
|
|
add_methods(this);
|
|
}
|
|
tree_node.neutral = 0;
|
|
tree_node.expanded = 1;
|
|
tree_node.collapsed = 2;
|
|
if (tree_node.prototype)
|
|
add_methods(tree_node.prototype);
|
|
|
|
//--------------Definition of class tree_control------------------------------//
|
|
|
|
function tree_control__add(text, link, hide)
|
|
{
|
|
return this.root.add(text, link, hide);
|
|
}
|
|
function tree_control__draw()
|
|
{
|
|
var tree = get_tree();
|
|
var dom = dom_support();
|
|
var element = dom ? elt_by_id('tree_control') : null;
|
|
if (element || !dom || tree.drawn) {
|
|
var html = tree.html();
|
|
if (tree.dump_html) {
|
|
var pat = new RegExp("<", "g");
|
|
html = "<pre>" + html.replace(pat, "<") + "</pre>";
|
|
if (document.body.innerHTML)
|
|
document.body.innerHTML = html;
|
|
else
|
|
document.write(html);
|
|
} else if (dom) {
|
|
element.innerHTML = html;
|
|
} else {
|
|
document.open();
|
|
document.write(
|
|
"<body>" + html +
|
|
( major_version("MSIE") == 3 ?
|
|
"<noscript>" :
|
|
document.layers ?
|
|
"<layer visibility='hide'>" :
|
|
"<table width=0 height=0 style='" +
|
|
"visibility:hidden;display:none'><tr><td>" )
|
|
);
|
|
document.close();
|
|
}
|
|
tree.drawn = true;
|
|
tree.load();
|
|
} else {
|
|
var t = navigator.userAgent.indexOf("Clue") != -1 ? 500 : 100;
|
|
setTimeout("tree_control__draw()", t);
|
|
}
|
|
}
|
|
function tree_control__find(id)
|
|
{
|
|
var indices = id.split(".");
|
|
var node = this.root;
|
|
for (var z = 1; z < indices.length; ++z)
|
|
node = node.kids[indices[z] - 1];
|
|
return node;
|
|
}
|
|
function tree_control__html()
|
|
{
|
|
return "<table><tr><td align='left'><table width=150><tr><td>" +
|
|
"<h1 class=tree-caption>" + this.caption + "</h1></td></tr>" +
|
|
( !static_display() ?
|
|
"<tr><td><p class='tree-sync'><a title='reload current " +
|
|
"page with a url suitable for bookmarking' class=" +
|
|
"'tree-sync' href='javascript:get_tree().sync()'>" +
|
|
"[link to this page]</a></p></td></tr>" :
|
|
"" ) +
|
|
"</table></td></tr><tr><td>" + this.root.print_kids(0) +
|
|
"</td></tr></table>";
|
|
}
|
|
function load_target(url)
|
|
{
|
|
var target;
|
|
if ((target = target_frame()) && target.location.href != url)
|
|
target.location.replace(url);
|
|
else {
|
|
setTimeout("load_target('" + url + "')", 100);
|
|
}
|
|
}
|
|
function tree_control__load()
|
|
{
|
|
var query;
|
|
if ((query = top.location.search).length == 0)
|
|
return;
|
|
query = query.substring(1);
|
|
var eq;
|
|
if ((eq = query.indexOf("=")) != -1) {
|
|
if (query.substring(0, 4) == "page") {
|
|
load_target(unescape(query.substring(eq + 1)));
|
|
return;
|
|
}
|
|
query = query.substring(eq + 1);
|
|
}
|
|
var indices = query.split(".");
|
|
if (!indices.length)
|
|
return;
|
|
this.reset();
|
|
var node = this.root;
|
|
for (var z = 0; z < indices.length; ++z) {
|
|
var i = parseInt(indices[z]) - 1;
|
|
if (!node.kids || i < 0 || node.kids.length <= i)
|
|
break;
|
|
node = node.kids[i];
|
|
node.toggle(/*z != indices.length - 1*/);
|
|
}
|
|
if (node.link)
|
|
load_target(node.link);
|
|
}
|
|
function tree_control__recurse(op)
|
|
{
|
|
var stack = new Array();
|
|
stack[stack.length] = this.root;
|
|
while (stack.length) {
|
|
var node = stack[stack.length - 1];
|
|
stack.length -=1 ; // Konqueror 2.
|
|
op(node);
|
|
if (node.kids)
|
|
for (var z = 0; z < node.kids.length; ++z)
|
|
stack[stack.length] = node.kids[z];
|
|
}
|
|
}
|
|
function tree_control__reset()
|
|
{
|
|
if (!dom_support())
|
|
return;
|
|
this.recurse(new Function("x", "if (x.parent()) x.toggle(false);"));
|
|
}
|
|
function sync_node(node)
|
|
{
|
|
if (!node.link)
|
|
return;
|
|
var tgt = target_frame().location.href;
|
|
var pos;
|
|
if ((pos = tgt.indexOf("?")) != -1)
|
|
tgt = tgt.substring(0, pos);
|
|
if (node.link.indexOf("://") != -1) {
|
|
if (node.link != tgt)
|
|
return;
|
|
} else {
|
|
var base = window.location.href;
|
|
if ((pos = base.lastIndexOf("/")) != -1)
|
|
base = base.substring(0, pos + 1);
|
|
if (base + node.link != tgt)
|
|
return;
|
|
}
|
|
window.success = true;
|
|
var href = replace_query( get_tree().top_url,
|
|
"path=" + node.id.substring(1) );
|
|
top.location.replace(href);
|
|
}
|
|
function tree_control__sync()
|
|
{
|
|
if (!dom_support() || self == top)
|
|
return;
|
|
window.success = false;
|
|
get_tree().recurse(sync_node);
|
|
if (!window.success)
|
|
top.location.replace(
|
|
replace_query( get_tree().top_url,
|
|
"page=" + escape(target_frame().location.href) )
|
|
);
|
|
}
|
|
function tree_control(target)
|
|
{
|
|
// Member data
|
|
this.root = new tree_node("");
|
|
this.target = target ? target : "_self";
|
|
this.dump_html = false;
|
|
this.caption = "Contents";
|
|
this.numbered = true;
|
|
this.indent = 15;
|
|
this.drawn = false;
|
|
this.top_url = top.location.href; // For Opera.
|
|
|
|
this.root.state = tree_node.expanded;
|
|
this.root.id = "";
|
|
|
|
// Member functions
|
|
this.add = tree_control__add;
|
|
this.draw = tree_control__draw;
|
|
this.find = tree_control__find;
|
|
this.html = tree_control__html;
|
|
this.load = tree_control__load;
|
|
this.recurse = tree_control__recurse;
|
|
this.reset = tree_control__reset;
|
|
this.sync = tree_control__sync;
|
|
document.tree_control = this;
|
|
}
|
|
tree_control.sync = tree_control__sync; |