1/*
2 * Navigation allows movement using the arrow keys through the search results.
3 *
4 * When using this library you will need to set scrollIntoView to the
5 * appropriate function for your layout.  Use scrollInWindow if the container
6 * is not scrollable and scrollInElement if the container is a separate
7 * scrolling region.
8 */
9Navigation = new function() {
10  this.initNavigation = function() {
11    var _this = this;
12
13    $(document).keydown(function(e) {
14      _this.onkeydown(e);
15    }).keyup(function(e) {
16      _this.onkeyup(e);
17    });
18
19    this.navigationActive = true;
20  }
21
22  this.setNavigationActive = function(state) {
23    this.navigationActive = state;
24    this.clearMoveTimeout();
25  }
26
27  this.onkeyup = function(e) {
28    if (!this.navigationActive) return;
29
30    switch(e.keyCode) {
31      case 37: //Event.KEY_LEFT:
32      case 38: //Event.KEY_UP:
33      case 39: //Event.KEY_RIGHT:
34      case 40: //Event.KEY_DOWN:
35        this.clearMoveTimeout();
36        break;
37    }
38  }
39
40  this.onkeydown = function(e) {
41    if (!this.navigationActive) return;
42    switch(e.keyCode) {
43      case 37: //Event.KEY_LEFT:
44        if (this.moveLeft()) e.preventDefault();
45        break;
46      case 38: //Event.KEY_UP:
47        if (e.keyCode == 38 || e.ctrlKey) {
48          if (this.moveUp()) e.preventDefault();
49          this.startMoveTimeout(false);
50        }
51        break;
52      case 39: //Event.KEY_RIGHT:
53        if (this.moveRight()) e.preventDefault();
54        break;
55      case 40: //Event.KEY_DOWN:
56        if (e.keyCode == 40 || e.ctrlKey) {
57          if (this.moveDown()) e.preventDefault();
58          this.startMoveTimeout(true);
59        }
60        break;
61      case 13: //Event.KEY_RETURN:
62        if (this.$current)
63          e.preventDefault();
64          this.select(this.$current);
65        break;
66    }
67    if (e.ctrlKey && e.shiftKey) this.select(this.$current);
68  }
69
70  this.clearMoveTimeout = function() {
71    clearTimeout(this.moveTimeout);
72    this.moveTimeout = null;
73  }
74
75  this.startMoveTimeout = function(isDown) {
76    if (!$.browser.mozilla && !$.browser.opera) return;
77    if (this.moveTimeout) this.clearMoveTimeout();
78    var _this = this;
79
80    var go = function() {
81      if (!_this.moveTimeout) return;
82      _this[isDown ? 'moveDown' : 'moveUp']();
83      _this.moveTimout = setTimeout(go, 100);
84    }
85    this.moveTimeout = setTimeout(go, 200);
86  }
87
88  this.moveRight = function() {
89  }
90
91  this.moveLeft = function() {
92  }
93
94  this.move = function(isDown) {
95  }
96
97  this.moveUp = function() {
98    return this.move(false);
99  }
100
101  this.moveDown = function() {
102    return this.move(true);
103  }
104
105  /*
106   * Scrolls to the given element in the scrollable element view.
107   */
108  this.scrollInElement = function(element, view) {
109    var offset, viewHeight, viewScroll, height;
110    offset = element.offsetTop;
111    height = element.offsetHeight;
112    viewHeight = view.offsetHeight;
113    viewScroll = view.scrollTop;
114
115    if (offset - viewScroll + height > viewHeight) {
116      view.scrollTop = offset - viewHeight + height;
117    }
118    if (offset < viewScroll) {
119      view.scrollTop = offset;
120    }
121  }
122
123  /*
124   * Scrolls to the given element in the window.  The second argument is
125   * ignored
126   */
127  this.scrollInWindow = function(element, ignored) {
128    var offset, viewHeight, viewScroll, height;
129    offset = element.offsetTop;
130    height = element.offsetHeight;
131    viewHeight = window.innerHeight;
132    viewScroll = window.scrollY;
133
134    if (offset - viewScroll + height > viewHeight) {
135      window.scrollTo(window.scrollX, offset - viewHeight + height);
136    }
137    if (offset < viewScroll) {
138      window.scrollTo(window.scrollX, offset);
139    }
140  }
141}
142
143