apphunk 0.1.1 → 0.3.0

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