1// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) 2// (C) Copyright 2003-2007 Jonathan Turkanis 3// Distributed under the Boost Software License, Version 1.0. (See accompanying 4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) 5 6//--------------Event-handlers------------------------------------------------// 7 8function toggle(id) { get_tree().find(id).toggle(); } 9function blur_tree() 10{ 11 if ( window.event && 12 window.event.srcElement && 13 window.event.srcElement.blur && 14 window.event.srcElement != document.body ) 15 window.event.srcElement.blur(); 16 else if (target_frame()) 17 target_frame().window.focus(); 18} 19document.onclick = blur_tree; 20 21//--------------Netscape 4.x-specific-----------------------------------------// 22 23window.saved_width = window.outerWidth; 24function reload_tree() 25{ 26 if (window.outerWidth != window.saved_width) 27 window.location.reload(); 28} 29if (window.Event && Event.RESIZE) { 30 window.captureEvents(Event.RESIZE); 31 window.onResize = reload_tree; 32} 33 34//--------------Functions for browser-sniffing--------------------------------// 35 36function major_version(app) 37{ 38 var index = navigator.userAgent.indexOf(app); 39 if (index == -1) 40 return -1; 41 return parseInt(navigator.userAgent.charAt(index + app.length + 1)); 42} 43function dom_support() 44{ 45 if (dom_support.cache == null) 46 dom_support.cache = dom_support_impl(); 47 return dom_support.cache; 48} 49function dom_support_impl() 50{ 51 var version; 52 if ( (version = major_version("Mozilla")) != -1 && 53 navigator.userAgent.indexOf("compatible") == -1 ) 54 return version > 4; 55 if ((version = major_version("Opera")) != -1) 56 return version > 6; 57 if ((version = major_version("Konqueror")) != -1) 58 return version > 2; 59 if ((version = major_version("Links")) != -1) 60 return false; 61 return document.getElementById || document.all; 62} 63 64//--------------Utility functions---------------------------------------------// 65 66function target_frame() 67{ 68 return get_tree() ? top.frames[get_tree().target] : null; 69} 70function get_tree() { return document.tree_control; } 71function static_display() { return !dom_support() || get_tree().dump_html; } 72function elt_by_id(id) 73{ 74 return document.all ? 75 document.all[id] : 76 document.getElementById ? 77 document.getElementById(id) : 78 null; 79} 80function replace_query(url, query) 81{ 82 var pos; 83 if ((pos = url.indexOf("?")) != -1) 84 url = url.substring(0, pos); 85 return url + "?" + query; 86} 87 88//--------------Functions for HTML-generation---------------------------------// 89 90function icon_char(state) 91{ 92 return state == tree_node.expanded ? 93 "-" : 94 state == tree_node.collapsed ? 95 "+" : 96 " "; 97} 98function html_list(id, display, margin) 99{ 100 return "<div id='" + id + "' style='white-space:nowrap;display:" + 101 display + "'>"; 102} 103function html_list_item(content) 104{ 105 return "\n<div class='tree-item'>" + content + "</div>"; 106} 107function html_anchor(content, cl, href, target) 108{ 109 return "<a class='" + cl + "' onfocus='blur_tree()" + 110 "' href='" + href + "'" + 111 (target ? " target='" + target + "'" : "") + 112 ">" + content + "</a>"; 113} 114 115//--------------Definition of class tree_node---------------------------------// 116 117function tree_node__add(text_or_node, link_or_hide, hide) 118{ 119 if (this.state == tree_node.neutral) 120 this.state = tree_node.collapsed; 121 var k; 122 if (text_or_node.length != null) { 123 k = new tree_node(text_or_node, link_or_hide); 124 k.hide_kids = hide != null ? hide : false; 125 } else { 126 k = text_or_node; 127 k.hide_kids = link_or_hide != null ? link_or_hide : false; 128 } 129 k.mom = this; 130 if (this.kids == null) 131 this.kids = new Array(); 132 this.kids[this.kids.length] = k; 133 return k; 134} 135function tree_node__level() 136{ 137 var level; 138 var node; 139 for (node = this.mom, level = -1; node; node = node.mom, ++level) 140 ; 141 return level; 142} 143function tree_node__parent() { return this.mom; } 144function tree_node__print() 145{ 146 var icon = 147 !static_display() ? 148 "<span style='font-family:monospace' class='tree-icon' id='icon" + 149 this.id + "'>" + icon_char(this.state) + "</span> " : 150 ""; 151 var handler = 152 !static_display() && this.kids ? 153 "javascript:toggle(\"id" + this.id + "\")" : 154 ""; 155 var text = "<span class='tree-text'>" + this.text + "</span>" 156 var tree = get_tree(); 157 var indent = tree.indent * this.level(); 158 return html_list_item( 159 "<div style='margin-left:" + (2 * indent) + 160 ";text-indent:-" + indent + "'>" + 161 ( !tree.dump_html ? 162 this.kids ? 163 html_anchor(icon, "tree-icon", handler) : 164 icon : 165 "" ) + 166 ( tree.numbered ? 167 "" + "<span class='tree-label'>" + 168 this.id.substring(1) + "</span>" : 169 "" ) + 170 " " + 171 ( this.link ? 172 html_anchor( text, "tree-text", this.link, 173 tree.target ) : 174 text ) + 175 "</div>" + 176 this.print_kids() 177 ); 178} 179function tree_node__print_kids(margin) 180{ 181 var result = ""; 182 if (this.kids != null && (!static_display() || !this.hide_kids)) { 183 if (margin == null) 184 margin = get_tree().indent; 185 result += html_list( "list" + this.id, 186 this.state == tree_node.collapsed && 187 !static_display() 188 ? "none" : "", 189 margin ); 190 for (var z = 0; z < this.kids.length; ++z) { 191 var k = this.kids[z]; 192 k.id = this.id + "." + (z + 1); 193 result += k.print(); 194 } 195 result += "</div>"; 196 } 197 return result; 198} 199function tree_node__toggle(expand) 200{ 201 if ( static_display() || 202 this.kids == null || 203 expand != null && expand == 204 (this.state == tree_node.expanded) ) 205 { 206 return; 207 } 208 this.state = 209 this.state == tree_node.expanded ? 210 tree_node.collapsed : 211 tree_node.expanded; 212 elt_by_id("icon" + this.id).innerHTML = 213 icon_char(this.state); 214 elt_by_id("list" + this.id).style.display = 215 this.state == tree_node.expanded ? 216 "" : 217 "none"; 218} 219function add_methods(obj) 220{ 221 obj.add = tree_node__add; 222 obj.level = tree_node__level; 223 obj.parent = tree_node__parent; 224 obj.print = tree_node__print; 225 obj.print_kids = tree_node__print_kids; 226 obj.toggle = tree_node__toggle; 227} 228function tree_node(text, link) 229{ 230 // Member data 231 this.text = text; 232 this.link = link; 233 this.mom = null; 234 this.kids = null; 235 this.id = null; 236 this.state = 0; // Neutral. 237 238 if (!add_methods.prototype) 239 add_methods(this); 240} 241tree_node.neutral = 0; 242tree_node.expanded = 1; 243tree_node.collapsed = 2; 244if (tree_node.prototype) 245 add_methods(tree_node.prototype); 246 247//--------------Definition of class tree_control------------------------------// 248 249function tree_control__add(text, link, hide) 250{ 251 return this.root.add(text, link, hide); 252} 253function tree_control__draw() 254{ 255 var tree = get_tree(); 256 var dom = dom_support(); 257 var element = dom ? elt_by_id('tree_control') : null; 258 if (element || !dom || tree.drawn) { 259 var html = tree.html(); 260 if (tree.dump_html) { 261 var pat = new RegExp("<", "g"); 262 html = "<pre>" + html.replace(pat, "<") + "</pre>"; 263 if (document.body.innerHTML) 264 document.body.innerHTML = html; 265 else 266 document.write(html); 267 } else if (dom) { 268 element.innerHTML = html; 269 } else { 270 document.open(); 271 document.write( 272 "<body>" + html + 273 ( major_version("MSIE") == 3 ? 274 "<noscript>" : 275 document.layers ? 276 "<layer visibility='hide'>" : 277 "<table width=0 height=0 style='" + 278 "visibility:hidden;display:none'><tr><td>" ) 279 ); 280 document.close(); 281 } 282 tree.drawn = true; 283 tree.load(); 284 } else { 285 var t = navigator.userAgent.indexOf("Clue") != -1 ? 500 : 100; 286 setTimeout("tree_control__draw()", t); 287 } 288} 289function tree_control__find(id) 290{ 291 var indices = id.split("."); 292 var node = this.root; 293 for (var z = 1; z < indices.length; ++z) 294 node = node.kids[indices[z] - 1]; 295 return node; 296} 297function tree_control__html() 298{ 299 return "<table><tr><td align='left'><table width=150><tr><td>" + 300 "<h1 class=tree-caption>" + this.caption + "</h1></td></tr>" + 301 ( !static_display() ? 302 "<tr><td><p class='tree-sync'><a title='reload current " + 303 "page with a url suitable for bookmarking' class=" + 304 "'tree-sync' href='javascript:get_tree().sync()'>" + 305 "[link to this page]</a></p></td></tr>" : 306 "" ) + 307 "</table></td></tr><tr><td>" + this.root.print_kids(0) + 308 "</td></tr></table>"; 309} 310function load_target(url) 311{ 312 var target; 313 if ((target = target_frame()) && target.location.href != url) 314 target.location.replace(url); 315 else { 316 setTimeout("load_target('" + url + "')", 100); 317 } 318} 319function tree_control__load() 320{ 321 var query; 322 if ((query = top.location.search).length == 0) 323 return; 324 query = query.substring(1); 325 var eq; 326 if ((eq = query.indexOf("=")) != -1) { 327 if (query.substring(0, 4) == "page") { 328 load_target(unescape(query.substring(eq + 1))); 329 return; 330 } 331 query = query.substring(eq + 1); 332 } 333 var indices = query.split("."); 334 if (!indices.length) 335 return; 336 this.reset(); 337 var node = this.root; 338 for (var z = 0; z < indices.length; ++z) { 339 var i = parseInt(indices[z]) - 1; 340 if (!node.kids || i < 0 || node.kids.length <= i) 341 break; 342 node = node.kids[i]; 343 node.toggle(/*z != indices.length - 1*/); 344 } 345 if (node.link) 346 load_target(node.link); 347} 348function tree_control__recurse(op) 349{ 350 var stack = new Array(); 351 stack[stack.length] = this.root; 352 while (stack.length) { 353 var node = stack[stack.length - 1]; 354 stack.length -=1 ; // Konqueror 2. 355 op(node); 356 if (node.kids) 357 for (var z = 0; z < node.kids.length; ++z) 358 stack[stack.length] = node.kids[z]; 359 } 360} 361function tree_control__reset() 362{ 363 if (!dom_support()) 364 return; 365 this.recurse(new Function("x", "if (x.parent()) x.toggle(false);")); 366} 367function sync_node(node) 368{ 369 if (!node.link) 370 return; 371 var tgt = target_frame().location.href; 372 var pos; 373 if ((pos = tgt.indexOf("?")) != -1) 374 tgt = tgt.substring(0, pos); 375 if (node.link.indexOf("://") != -1) { 376 if (node.link != tgt) 377 return; 378 } else { 379 var base = window.location.href; 380 if ((pos = base.lastIndexOf("/")) != -1) 381 base = base.substring(0, pos + 1); 382 if (base + node.link != tgt) 383 return; 384 } 385 window.success = true; 386 var href = replace_query( get_tree().top_url, 387 "path=" + node.id.substring(1) ); 388 top.location.replace(href); 389} 390function tree_control__sync() 391{ 392 if (!dom_support() || self == top) 393 return; 394 window.success = false; 395 get_tree().recurse(sync_node); 396 if (!window.success) 397 top.location.replace( 398 replace_query( get_tree().top_url, 399 "page=" + escape(target_frame().location.href) ) 400 ); 401} 402function tree_control(target) 403{ 404 // Member data 405 this.root = new tree_node(""); 406 this.target = target ? target : "_self"; 407 this.dump_html = false; 408 this.caption = "Contents"; 409 this.numbered = true; 410 this.indent = 15; 411 this.drawn = false; 412 this.top_url = top.location.href; // For Opera. 413 414 this.root.state = tree_node.expanded; 415 this.root.id = ""; 416 417 // Member functions 418 this.add = tree_control__add; 419 this.draw = tree_control__draw; 420 this.find = tree_control__find; 421 this.html = tree_control__html; 422 this.load = tree_control__load; 423 this.recurse = tree_control__recurse; 424 this.reset = tree_control__reset; 425 this.sync = tree_control__sync; 426 document.tree_control = this; 427} 428tree_control.sync = tree_control__sync;