]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
8 | function toggle(id) { get_tree().find(id).toggle(); } | |
9 | function 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 | } | |
19 | document.onclick = blur_tree; | |
20 | ||
21 | //--------------Netscape 4.x-specific-----------------------------------------// | |
22 | ||
23 | window.saved_width = window.outerWidth; | |
24 | function reload_tree() | |
25 | { | |
26 | if (window.outerWidth != window.saved_width) | |
27 | window.location.reload(); | |
28 | } | |
29 | if (window.Event && Event.RESIZE) { | |
30 | window.captureEvents(Event.RESIZE); | |
31 | window.onResize = reload_tree; | |
32 | } | |
33 | ||
34 | //--------------Functions for browser-sniffing--------------------------------// | |
35 | ||
36 | function 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 | } | |
43 | function dom_support() | |
44 | { | |
45 | if (dom_support.cache == null) | |
46 | dom_support.cache = dom_support_impl(); | |
47 | return dom_support.cache; | |
48 | } | |
49 | function 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 | ||
66 | function target_frame() | |
67 | { | |
68 | return get_tree() ? top.frames[get_tree().target] : null; | |
69 | } | |
70 | function get_tree() { return document.tree_control; } | |
71 | function static_display() { return !dom_support() || get_tree().dump_html; } | |
72 | function elt_by_id(id) | |
73 | { | |
74 | return document.all ? | |
75 | document.all[id] : | |
76 | document.getElementById ? | |
77 | document.getElementById(id) : | |
78 | null; | |
79 | } | |
80 | function 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 | ||
90 | function icon_char(state) | |
91 | { | |
92 | return state == tree_node.expanded ? | |
93 | "-" : | |
94 | state == tree_node.collapsed ? | |
95 | "+" : | |
96 | " "; | |
97 | } | |
98 | function html_list(id, display, margin) | |
99 | { | |
100 | return "<div id='" + id + "' style='white-space:nowrap;display:" + | |
101 | display + "'>"; | |
102 | } | |
103 | function html_list_item(content) | |
104 | { | |
105 | return "\n<div class='tree-item'>" + content + "</div>"; | |
106 | } | |
107 | function 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 | ||
117 | function 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 | } | |
135 | function 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 | } | |
143 | function tree_node__parent() { return this.mom; } | |
144 | function 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 | } | |
179 | function 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 | } | |
199 | function 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 | } | |
219 | function 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 | } | |
228 | function 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 | } | |
241 | tree_node.neutral = 0; | |
242 | tree_node.expanded = 1; | |
243 | tree_node.collapsed = 2; | |
244 | if (tree_node.prototype) | |
245 | add_methods(tree_node.prototype); | |
246 | ||
247 | //--------------Definition of class tree_control------------------------------// | |
248 | ||
249 | function tree_control__add(text, link, hide) | |
250 | { | |
251 | return this.root.add(text, link, hide); | |
252 | } | |
253 | function 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 | } | |
289 | function 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 | } | |
297 | function 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 | } | |
310 | function 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 | } | |
319 | function 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 | } | |
348 | function 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 | } | |
361 | function tree_control__reset() | |
362 | { | |
363 | if (!dom_support()) | |
364 | return; | |
365 | this.recurse(new Function("x", "if (x.parent()) x.toggle(false);")); | |
366 | } | |
367 | function 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 | } | |
390 | function 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 | } | |
402 | function 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 | } | |
428 | tree_control.sync = tree_control__sync; |