voloko-sdoc 0.0.5 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. data/README +1 -1
  2. data/bin/sdoc +0 -1
  3. data/bin/sdoc-merge +12 -0
  4. data/lib/sdoc.rb +15 -7
  5. data/lib/sdoc/generator/shtml.rb +671 -0
  6. data/lib/sdoc/generator/template/shtml/_context.rhtml +163 -0
  7. data/lib/sdoc/generator/template/shtml/class.rhtml +46 -0
  8. data/lib/sdoc/generator/template/shtml/file.rhtml +37 -0
  9. data/lib/sdoc/generator/template/shtml/index.rhtml +14 -0
  10. data/lib/sdoc/generator/template/shtml/resources/css/main.css +191 -0
  11. data/lib/sdoc/{generators/template/shtml/resources/css/master-frameset.css → generator/template/shtml/resources/css/panel.css} +83 -2
  12. data/lib/sdoc/{generators → generator}/template/shtml/resources/css/reset.css +0 -0
  13. data/lib/sdoc/{generators → generator}/template/shtml/resources/i/arrows.png +0 -0
  14. data/lib/sdoc/{generators → generator}/template/shtml/resources/i/results_bg.png +0 -0
  15. data/lib/sdoc/{generators → generator}/template/shtml/resources/i/tree_bg.png +0 -0
  16. data/lib/sdoc/{generators → generator}/template/shtml/resources/js/jquery-1.3.2.min.js +0 -0
  17. data/lib/sdoc/generator/template/shtml/resources/js/main.js +34 -0
  18. data/lib/sdoc/generator/template/shtml/resources/js/searchdoc.js +600 -0
  19. data/lib/sdoc/{generators/template/shtml/resources/panel.html → generator/template/shtml/resources/panel/index.html} +6 -6
  20. data/lib/sdoc/github.rb +64 -0
  21. data/lib/sdoc/merge.rb +166 -0
  22. metadata +117 -19
  23. data/lib/sdoc/code_objects.rb +0 -17
  24. data/lib/sdoc/generators/shtml_generator.rb +0 -354
  25. data/lib/sdoc/generators/template/shtml/resources/js/searchdoc.js +0 -595
  26. data/lib/sdoc/generators/template/shtml/shtml.rb +0 -615
  27. data/lib/sdoc/options.rb +0 -61
  28. data/test/options_test.rb +0 -33
  29. data/test/sdoc_test.rb +0 -7
@@ -96,7 +96,7 @@
96
96
  height: 46px;
97
97
  overflow: hidden;
98
98
  padding: 4px 10px 0 10px;
99
- cursor: default;
99
+ cursor: pointer;
100
100
  }
101
101
 
102
102
  .panel .result ul li h1
@@ -159,7 +159,76 @@
159
159
  .panel .result ul li.current:hover
160
160
  {
161
161
  background: #2965C0;
162
+ }
163
+
164
+ .panel .result ul li .badge
165
+ {
166
+ margin-right: 0.4em;
167
+ margin-left: -0.2em;
168
+ padding: 0 0.2em;
169
+ color: #000;
170
+ }
171
+
172
+ .panel .result ul li .badge_1
173
+ {
174
+ background: #ACDBF4;
175
+ }
176
+
177
+ .panel .result ul li.current .badge_1
178
+ {
179
+ background: #97BFD7;
180
+ }
181
+
182
+ .panel .result ul li .badge_2
183
+ {
184
+ background: #ACF3C3;
185
+ }
186
+
187
+ .panel .result ul li.current .badge_2
188
+ {
189
+ background: #98D7AC;
190
+ }
191
+
192
+ .panel .result ul li .badge_3
193
+ {
194
+ background: #E0F3AC;
195
+ }
196
+
197
+ .panel .result ul li.current .badge_3
198
+ {
199
+ background: #C4D798;
200
+ }
201
+
202
+ .panel .result ul li .badge_4
203
+ {
204
+ background: #D7CA98;
205
+ }
206
+
207
+ .panel .result ul li.current .badge_4
208
+ {
209
+ background: #A6B0AC;
210
+ }
211
+
212
+ .panel .result ul li .badge_5
213
+ {
214
+ background: #F3C8AC;
215
+ }
216
+
217
+ .panel .result ul li.current .badge_5
218
+ {
219
+ background: #D7B198;
220
+ }
221
+
222
+ .panel .result ul li .badge_6
223
+ {
224
+ background: #F3ACC3;
225
+ }
226
+
227
+ .panel .result ul li.current .badge_6
228
+ {
229
+ background: #D798AB;
162
230
  }
231
+
163
232
  /* Results (end) */
164
233
 
165
234
  /* Tree (begin) */ /**/
@@ -176,11 +245,17 @@
176
245
  z-index: 3;
177
246
  }
178
247
 
179
- .panel .tree > ul
248
+ .panel .tree ul
180
249
  {
181
250
  background: #EDF3FE url(../i/tree_bg.png);
251
+ }
252
+
253
+ .panel .tree li
254
+ {
255
+ cursor: pointer;
182
256
  }
183
257
 
258
+
184
259
  .panel .tree li .content
185
260
  {
186
261
  padding-left: 18px;
@@ -199,6 +274,7 @@
199
274
  position: absolute;
200
275
  left: 1px;
201
276
  top: 8px;
277
+ cursor: default;
202
278
  }
203
279
 
204
280
  .panel .tree li.closed .icon
@@ -229,6 +305,11 @@
229
305
  font-style: normal;
230
306
  }
231
307
 
308
+ .panel .tree ul li.empty
309
+ {
310
+ cursor: text;
311
+ }
312
+
232
313
  .panel .tree ul li.empty h1,
233
314
  .panel .tree ul li.empty p
234
315
  {
@@ -0,0 +1,34 @@
1
+ function toggleSource( id )
2
+ {
3
+ var elem
4
+ var link
5
+
6
+ if( document.getElementById )
7
+ {
8
+ elem = document.getElementById( id )
9
+ link = document.getElementById( "l_" + id )
10
+ }
11
+ else if ( document.all )
12
+ {
13
+ elem = eval( "document.all." + id )
14
+ link = eval( "document.all.l_" + id )
15
+ }
16
+ else
17
+ return false;
18
+
19
+ if( elem.style.display == "block" )
20
+ {
21
+ elem.style.display = "none"
22
+ link.innerHTML = "show"
23
+ }
24
+ else
25
+ {
26
+ elem.style.display = "block"
27
+ link.innerHTML = "hide"
28
+ }
29
+ }
30
+
31
+ function openCode( url )
32
+ {
33
+ window.open( url, "SOURCE_CODE", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=480,width=750" ).focus();
34
+ }
@@ -0,0 +1,600 @@
1
+ Searchdoc = {};
2
+
3
+ // navigation.js ------------------------------------------
4
+
5
+ Searchdoc.Navigation = new function() {
6
+ this.initNavigation = function() {
7
+ var _this = this;
8
+
9
+ $(document).keydown(function(e) {
10
+ _this.onkeydown(e);
11
+ }).keyup(function(e) {
12
+ _this.onkeyup(e);
13
+ });
14
+
15
+ this.navigationActive = true;
16
+ }
17
+
18
+ this.setNavigationActive = function(state) {
19
+ this.navigationActive = state;
20
+ this.clearMoveTimeout();
21
+ }
22
+
23
+
24
+ this.onkeyup = function(e) {
25
+ if (!this.navigationActive) return;
26
+ switch(e.keyCode) {
27
+ case 37: //Event.KEY_LEFT:
28
+ case 38: //Event.KEY_UP:
29
+ case 39: //Event.KEY_RIGHT:
30
+ case 40: //Event.KEY_DOWN:
31
+ this.clearMoveTimeout();
32
+ break;
33
+ }
34
+ }
35
+
36
+ this.onkeydown = function(e) {
37
+ if (!this.navigationActive) return;
38
+ switch(e.keyCode) {
39
+ case 37: //Event.KEY_LEFT:
40
+ this.moveLeft();
41
+ e.preventDefault();
42
+ break;
43
+ case 38: //Event.KEY_UP:
44
+ this.moveUp();
45
+ e.preventDefault();
46
+ this.startMoveTimeout(false);
47
+ break;
48
+ case 39: //Event.KEY_RIGHT:
49
+ this.moveRight();
50
+ e.preventDefault();
51
+ break;
52
+ case 40: //Event.KEY_DOWN:
53
+ this.moveDown();
54
+ e.preventDefault();
55
+ this.startMoveTimeout(true);
56
+ break;
57
+ case 9: //Event.KEY_TAB:
58
+ case 13: //Event.KEY_RETURN:
59
+ if (this.$current) this.select(this.$current);
60
+ break;
61
+ }
62
+ }
63
+
64
+ this.clearMoveTimeout = function() {
65
+ clearTimeout(this.moveTimeout);
66
+ this.moveTimeout = null;
67
+ }
68
+
69
+ this.startMoveTimeout = function(isDown) {
70
+ if (!$.browser.mozilla) return;
71
+ if (this.moveTimeout) this.clearMoveTimeout();
72
+ var _this = this;
73
+
74
+ var go = function() {
75
+ if (!_this.moveTimeout) return;
76
+ _this[isDown ? 'moveDown' : 'moveUp']();
77
+ _this.moveTimout = setTimeout(go, 100);
78
+ }
79
+ this.moveTimeout = setTimeout(go, 200);
80
+ }
81
+
82
+ this.moveRight = function() {
83
+ }
84
+
85
+ this.moveLeft = function() {
86
+ }
87
+
88
+ this.move = function(isDown) {
89
+ }
90
+
91
+ this.moveUp = function() {
92
+ this.move(false);
93
+ }
94
+
95
+ this.moveDown = function() {
96
+ this.move(true);
97
+ }
98
+ }
99
+
100
+
101
+ // scrollIntoView.js --------------------------------------
102
+
103
+ function scrollIntoView(element, view) {
104
+ var offset, viewHeight, viewScroll, height;
105
+ offset = element.offsetTop;
106
+ height = element.offsetHeight;
107
+ viewHeight = view.offsetHeight;
108
+ viewScroll = view.scrollTop;
109
+ if (offset - viewScroll + height > viewHeight) {
110
+ view.scrollTop = offset - viewHeight + height;
111
+ }
112
+ if (offset < viewScroll) {
113
+ view.scrollTop = offset;
114
+ }
115
+ }
116
+
117
+
118
+ // searcher.js --------------------------------------------
119
+
120
+ Searchdoc.Searcher = function(data) {
121
+ this.data = data;
122
+ this.handlers = [];
123
+ }
124
+
125
+ Searchdoc.Searcher.prototype = new function() {
126
+ var CHUNK_SIZE = 1000, // search is performed in chunks of 1000 for non-bloking user input
127
+ MAX_RESULTS = 100, // do not try to find more than 100 results
128
+ huid = 1, suid = 1,
129
+ runs = 0;
130
+
131
+
132
+ this.find = function(query) {
133
+ var queries = splitQuery(query),
134
+ regexps = buildRegexps(queries),
135
+ highlighters = buildHilighters(queries),
136
+ state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++},
137
+ _this = this;
138
+ this.currentSuid = state.n;
139
+
140
+ if (!query) return;
141
+
142
+ var run = function() {
143
+ // stop current search thread if new search started
144
+ if (state.n != _this.currentSuid) return;
145
+
146
+ var results = performSearch(_this.data, regexps, queries, highlighters, state),
147
+ hasMore = (state.limit > 0 && state.pass < 3);
148
+
149
+ triggerResults.call(_this, results, !hasMore);
150
+ if (hasMore) {
151
+ setTimeout(run, 2);
152
+ }
153
+ runs++;
154
+ };
155
+ runs = 0;
156
+
157
+ // start search thread
158
+ run();
159
+ }
160
+
161
+ /* ----- Events ------ */
162
+ this.ready = function(fn) {
163
+ fn.huid = huid;
164
+ this.handlers.push(fn);
165
+ }
166
+
167
+ /* ----- Utilities ------ */
168
+ function splitQuery(query) {
169
+ return jQuery.grep(query.split(/\s+/), function(string) { return !!string });
170
+ }
171
+
172
+ function buildRegexps(queries) {
173
+ return jQuery.map(queries, function(query) { return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i') });
174
+ }
175
+
176
+ function buildHilighters(queries) {
177
+ return jQuery.map(queries, function(query) {
178
+ return jQuery.map( query.split(''), function(l, i){ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2) } ).join('')
179
+ });
180
+ }
181
+
182
+ // function longMatchRegexp(index, longIndex, regexps) {
183
+ // for (var i = regexps.length - 1; i >= 0; i--){
184
+ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
185
+ // };
186
+ // return true;
187
+ // }
188
+
189
+
190
+ /* ----- Mathchers ------ */
191
+ function matchPass1(index, longIndex, queries, regexps) {
192
+ if (index.indexOf(queries[0]) != 0) return false;
193
+ for (var i=1, l = regexps.length; i < l; i++) {
194
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
195
+ };
196
+ return true;
197
+ }
198
+
199
+ function matchPass2(index, longIndex, queries, regexps) {
200
+ if (index.indexOf(queries[0]) == -1) return false;
201
+ for (var i=1, l = regexps.length; i < l; i++) {
202
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
203
+ };
204
+ return true;
205
+ }
206
+
207
+ function matchPassRegexp(index, longIndex, queries, regexps) {
208
+ for (var i=0, l = regexps.length; i < l; i++) {
209
+ if (!index.match(regexps[i]) && (i == 0 || !longIndex.indexOf(regexps[i]))) return false;
210
+ };
211
+ return true;
212
+ }
213
+
214
+
215
+ /* ----- Highlighters ------ */
216
+ function highlightRegexp(info, queries, regexps, highlighters) {
217
+ var result = createResult(info);
218
+ for (var i=0, l = regexps.length; i < l; i++) {
219
+ result.title = result.title.replace(regexps[i], highlighters[i]);
220
+ if (i > 0)
221
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
222
+ };
223
+ return result;
224
+ }
225
+
226
+ function hltSubstring(string, pos, length) {
227
+ return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
228
+ }
229
+
230
+ function highlightQuery(info, queries, regexps, highlighters) {
231
+ var result = createResult(info), pos = 0, lcTitle = result.title.toLowerCase();
232
+ pos = lcTitle.indexOf(queries[0]);
233
+ if (pos != -1) {
234
+ result.title = hltSubstring(result.title, pos, queries[0].length);
235
+ }
236
+ for (var i=1, l = regexps.length; i < l; i++) {
237
+ result.title = result.title.replace(regexps[i], highlighters[i]);
238
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
239
+ };
240
+ return result;
241
+ }
242
+
243
+ function createResult(info) {
244
+ var result = {};
245
+ result.title = info[0];
246
+ result.namespace = info[1];
247
+ result.path = info[2];
248
+ result.params = info[3];
249
+ result.snippet = info[4];
250
+ result.badge = info[6];
251
+ return result;
252
+ }
253
+
254
+ /* ----- Searching ------ */
255
+ function performSearch(data, regexps, queries, highlighters, state) {
256
+ var searchIndex = data.searchIndex, // search by title first and then by source
257
+ longSearchIndex = data.longSearchIndex,
258
+ info = data.info,
259
+ result = [],
260
+ i = state.from,
261
+ l = searchIndex.length,
262
+ togo = CHUNK_SIZE,
263
+ matchFunc, hltFunc;
264
+
265
+ while (state.pass < 3 && state.limit > 0 && togo > 0) {
266
+ if (state.pass == 0) {
267
+ matchFunc = matchPass1;
268
+ hltFunc = highlightQuery;
269
+ } else if (state.pass == 1) {
270
+ matchFunc = matchPass1;
271
+ hltFunc = highlightQuery;
272
+ } else if (state.pass == 2) {
273
+ matchFunc = matchPassRegexp;
274
+ hltFunc = highlightRegexp;
275
+ }
276
+
277
+ for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
278
+ if (info[i].n == state.n) continue;
279
+ if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
280
+ info[i].n = state.n;
281
+ result.push(hltFunc(info[i], queries, regexps, highlighters));
282
+ state.limit--;
283
+ }
284
+ };
285
+ if (searchIndex.length <= i) {
286
+ state.pass++;
287
+ i = state.from = 0;
288
+ } else {
289
+ state.from = i;
290
+ }
291
+ }
292
+ return result;
293
+ }
294
+
295
+ function triggerResults(results, isLast) {
296
+ jQuery.each(this.handlers, function(i, fn) { fn.call(this, results, isLast) })
297
+ }
298
+ }
299
+
300
+
301
+
302
+
303
+ // panel.js -----------------------------------------------
304
+
305
+ Searchdoc.Panel = function(element, data, tree, frame) {
306
+ this.$element = $(element);
307
+ this.$input = $('input', element).eq(0);
308
+ this.$result = $('.result ul', element).eq(0);
309
+ this.frame = frame;
310
+ this.$current = null;
311
+ this.$view = this.$result.parent();
312
+ this.data = data;
313
+ this.searcher = new Searchdoc.Searcher(data.index);
314
+ this.tree = new Searchdoc.Tree($('.tree', element), tree, this);
315
+ this.init();
316
+ }
317
+
318
+ Searchdoc.Panel.prototype = $.extend({}, Searchdoc.Navigation, new function() {
319
+ var suid = 1;
320
+
321
+ this.init = function() {
322
+ var _this = this;
323
+ var observer = function() {
324
+ _this.search(_this.$input[0].value);
325
+ };
326
+ this.$input.keyup(observer);
327
+ this.$input.click(observer); // mac's clear field
328
+
329
+ this.searcher.ready(function(results, isLast) {
330
+ _this.addResults(results, isLast);
331
+ })
332
+
333
+ this.$result.click(function(e) {
334
+ _this.$current.removeClass('current');
335
+ _this.$current = $(e.target).closest('li').addClass('current');
336
+ _this.select();
337
+ _this.$input.focus();
338
+ });
339
+
340
+ this.initNavigation();
341
+ this.setNavigationActive(false);
342
+ }
343
+
344
+ this.search = function(value) {
345
+ value = jQuery.trim(value).toLowerCase();
346
+ if (value) {
347
+ this.$element.removeClass('panel_tree').addClass('panel_results');
348
+ this.tree.setNavigationActive(false);
349
+ this.setNavigationActive(true);
350
+ } else {
351
+ this.$element.addClass('panel_tree').removeClass('panel_results');
352
+ this.tree.setNavigationActive(true);
353
+ this.setNavigationActive(false);
354
+ }
355
+ if (value != this.lastQuery) {
356
+ this.lastQuery = value;
357
+ this.firstRun = true;
358
+ this.searcher.find(value);
359
+ }
360
+ }
361
+
362
+ this.addResults = function(results, isLast) {
363
+ var target = this.$result.get(0);
364
+ if (this.firstRun && (results.length > 0 || isLast)) {
365
+ this.$current = null;
366
+ this.$result.empty();
367
+ }
368
+ for (var i=0, l = results.length; i < l; i++) {
369
+ target.appendChild(renderItem.call(this, results[i]));
370
+ };
371
+ if (this.firstRun && results.length > 0) {
372
+ this.firstRun = false;
373
+ this.$current = $(target.firstChild);
374
+ this.$current.addClass('current');
375
+ scrollIntoView(this.$current[0], this.$view[0])
376
+ }
377
+ if (jQuery.browser.msie) this.$element[0].className += '';
378
+ }
379
+
380
+ this.open = function(src) {
381
+ this.frame.location.href = '../' + src;
382
+ }
383
+
384
+ this.select = function() {
385
+ this.open(this.$current.data('path'));
386
+ }
387
+
388
+ this.move = function(isDown) {
389
+ if (!this.$current) return;
390
+ var $next = this.$current[isDown ? 'next' : 'prev']();
391
+ if ($next.length) {
392
+ this.$current.removeClass('current');
393
+ $next.addClass('current');
394
+ scrollIntoView($next[0], this.$view[0]);
395
+ this.$current = $next;
396
+ }
397
+ }
398
+
399
+ function renderItem(result) {
400
+ var li = document.createElement('li'),
401
+ html = '', badge = result.badge;
402
+ html += '<h1>' + hlt(result.title);
403
+ if (result.params) html += '<i>' + result.params + '</i></h1>';
404
+ html += '<p>';
405
+ if (typeof badge != 'undefined') {
406
+ badge = badge % 6;
407
+ html += '<span class="badge badge_' + (badge + 1) + '">' + escapeHTML(this.data.badges[badge] || 'unknown') + '</span>';
408
+ }
409
+ html += hlt(result.namespace) + '</p>';
410
+ if (result.snippet) html += '<p class="snippet">' + escapeHTML(result.snippet) + '</p>';
411
+ li.innerHTML = html;
412
+ jQuery.data(li, 'path', result.path);
413
+ return li;
414
+ }
415
+
416
+ function hlt(html) {
417
+ return escapeHTML(html).replace(/\u0001/g, '<b>').replace(/\u0002/g, '</b>')
418
+ }
419
+
420
+ function escapeHTML(html) {
421
+ return html.replace(/[&<>]/g, function(c) {
422
+ return '&#' + c.charCodeAt(0) + ';';
423
+ });
424
+ }
425
+
426
+ });
427
+
428
+ // tree.js ------------------------------------------------
429
+
430
+ Searchdoc.Tree = function(element, tree, panel) {
431
+ this.$element = $(element);
432
+ this.$list = $('ul', element);
433
+ this.tree = tree;
434
+ this.panel = panel;
435
+ this.init();
436
+ }
437
+
438
+ Searchdoc.Tree.prototype = $.extend({}, Searchdoc.Navigation, new function() {
439
+ this.init = function() {
440
+ var stopper = document.createElement('li');
441
+ stopper.className = 'stopper';
442
+ this.$list[0].appendChild(stopper);
443
+ for (var i=0, l = this.tree.length; i < l; i++) {
444
+ buildAndAppendItem.call(this, this.tree[i], 0, stopper);
445
+ };
446
+ var _this = this;
447
+ this.$list.click(function(e) {
448
+ var $target = $(e.target),
449
+ $li = $target.closest('li');
450
+ if ($target.hasClass('icon')) {
451
+ _this.toggle($li);
452
+ } else {
453
+ _this.select($li);
454
+ }
455
+ })
456
+
457
+ this.initNavigation();
458
+ }
459
+
460
+ this.select = function($li) {
461
+ var path = $li[0].searchdoc_tree_data.path;
462
+ if (this.$current) this.$current.removeClass('current');
463
+ this.$current = $li.addClass('current');
464
+ if (path) this.panel.open(path);
465
+ }
466
+
467
+ this.toggle = function($li) {
468
+ var closed = !$li.hasClass('closed'),
469
+ children = $li[0].searchdoc_tree_data.children;
470
+ $li.toggleClass('closed');
471
+ for (var i=0, l = children.length; i < l; i++) {
472
+ toggleVis.call(this, $(children[i].li), !closed);
473
+ };
474
+ }
475
+
476
+ this.moveRight = function() {
477
+ if (!this.$current) {
478
+ this.select(this.$list.find('li:first'));
479
+ return;
480
+ }
481
+ if (this.$current.hasClass('closed')) {
482
+ this.toggle(this.$current);
483
+ }
484
+ }
485
+
486
+ this.moveLeft = function() {
487
+ if (!this.$current) {
488
+ this.select(this.$list.find('li:first'));
489
+ return;
490
+ }
491
+ if (!this.$current.hasClass('closed')) {
492
+ this.toggle(this.$current);
493
+ } else {
494
+ var level = this.$current[0].searchdoc_tree_data.level;
495
+ if (level == 0) return;
496
+ var $next = this.$current.prevAll('li.level_' + (level - 1) + ':visible:first');
497
+ this.$current.removeClass('current');
498
+ $next.addClass('current');
499
+ scrollIntoView($next[0], this.$element[0]);
500
+ this.$current = $next;
501
+ }
502
+ }
503
+
504
+ this.move = function(isDown) {
505
+ if (!this.$current) {
506
+ this.select(this.$list.find('li:first'));
507
+ return;
508
+ }
509
+ var next = this.$current[0];
510
+ if (isDown) {
511
+ do {
512
+ next = next.nextSibling;
513
+ if (next && next.style && next.style.display != 'none') break;
514
+ } while(next);
515
+ } else {
516
+ do {
517
+ next = next.previousSibling;
518
+ if (next && next.style && next.style.display != 'none') break;
519
+ } while(next);
520
+ }
521
+ if (next && next.className.indexOf('stopper') == -1) {
522
+ this.$current.removeClass('current');
523
+ $(next).addClass('current');
524
+ scrollIntoView(next, this.$element[0]);
525
+ this.$current = $(next);
526
+ }
527
+ }
528
+
529
+ function toggleVis($li, show) {
530
+ var closed = $li.hasClass('closed'),
531
+ children = $li[0].searchdoc_tree_data.children;
532
+ $li.css('display', show ? '' : 'none')
533
+ if (!show && this.$current && $li[0] == this.$current[0]) {
534
+ this.$current.removeClass('current');
535
+ this.$current = null;
536
+ }
537
+ for (var i=0, l = children.length; i < l; i++) {
538
+ toggleVis.call(this, $(children[i].li), show && !closed);
539
+ };
540
+ }
541
+
542
+ function buildAndAppendItem(item, level, before) {
543
+ var li = renderItem(item, level),
544
+ list = this.$list[0];
545
+ item.li = li;
546
+ list.insertBefore(li, before);
547
+ for (var i=0, l = item[3].length; i < l; i++) {
548
+ buildAndAppendItem.call(this, item[3][i], level + 1, before);
549
+ };
550
+ return li;
551
+ }
552
+
553
+ function renderItem(item, level) {
554
+ var li = document.createElement('li'),
555
+ cnt = document.createElement('div'),
556
+ h1 = document.createElement('h1'),
557
+ p = document.createElement('p'),
558
+ icon, i;
559
+
560
+ li.appendChild(cnt);
561
+ li.style.paddingLeft = getOffset(level);
562
+ cnt.className = 'content';
563
+ if (!item[1]) li.className = 'empty ';
564
+ cnt.appendChild(h1);
565
+ // cnt.appendChild(p);
566
+ h1.appendChild(document.createTextNode(item[0]));
567
+ // p.appendChild(document.createTextNode(item[4]));
568
+ if (item[2]) {
569
+ i = document.createElement('i');
570
+ i.appendChild(document.createTextNode(item[2]));
571
+ h1.appendChild(i);
572
+ }
573
+ if (item[3].length > 0) {
574
+ icon = document.createElement('div');
575
+ icon.className = 'icon';
576
+ cnt.appendChild(icon);
577
+ }
578
+
579
+ // user direct assignement instead of $()
580
+ // it's 8x faster
581
+ // $(li).data('path', item[1])
582
+ // .data('children', item[3])
583
+ // .data('level', level)
584
+ // .css('display', level == 0 ? '' : 'none')
585
+ // .addClass('level_' + level)
586
+ // .addClass('closed');
587
+ li.searchdoc_tree_data = {
588
+ path: item[1],
589
+ children: item[3],
590
+ level: level
591
+ }
592
+ li.style.display = level == 0 ? '' : 'none';
593
+ li.className += 'level_' + level + ' closed';
594
+ return li;
595
+ }
596
+
597
+ function getOffset(level) {
598
+ return 5 + 18*level + 'px';
599
+ }
600
+ });