Skip to content

Commit 9e82805

Browse files
committed
adding keyboard navigation post
1 parent a832d0b commit 9e82805

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
---
2+
title: Adding Keyboard Navigation
3+
attribution: Remy Sharp
4+
status: needswork
5+
editrequired: 2
6+
source: http://jqueryfordesigners.com/adding-keyboard-navigation/
7+
---
8+
9+
##The problem
10+
11+
[Mathieu White](http://mathieuwhite.com/) got [in touch with me to ask](http://jqueryfordesigners.com/request/) how to add the keyboard support to his site. He wasn’t using my own slider code, he was using [Niall Doherty’s version](http://www.ndoherty.biz/coda-slider). Since changing the slider code was out of the question, and moving to my own carousel code to trigger the goto events would also be way too much work for a simple effect, I wanted to find a simple and easy to add solution. So to keep things as simple as possible, I worked out I should be able to layer on the functionality after the slider code was finished.
12+
13+
Since jQuery lends itself to finding something, then doing something to it, I would let the slider code run, then find the links on the page used to navigate the slider, and trigger them as appropriate on keyboard input.
14+
15+
The task is to slide the panels left or right, depending on which cursor key is pressed on the page.
16+
17+
##The solution
18+
19+
As Mathieu’s slider is the primary focus of the page, we want the keyboard support to apply from anywhere on the page. And we’re only navigating left and right, which won’t interfere with scrolling up and down the page.
20+
21+
We need a keyboard event listener on the document.documentElement element as this is the best point for a catch all element (to work in all browsers). If an input element is focused, and you press a key, it fires the keypress event on the input element, then on all the parent elements, which eventually hits the body element, then thedocumentElement then the the window.
22+
23+
Once we have our keyboard event listener, we need to determine whether the user pressed the left or right cursor key, and if they did trigger the effect.
24+
25+
Triggering the effect is the trick. We’re doing this by triggering a click on the navigation links. So we’re faking a user interaction. If the user pressed the right cursor key, we need to find the navigation link that’s currently selected (in this case it has a class of current), and find the link to the right, and trigger a click on this.
26+
27+
##Capturing key events
28+
29+
Then a keyboard key is pressed the event break into three separate events, which fire in the following order:
30+
- keydown
31+
- keypress
32+
- keyup
33+
34+
So I’m going to use the last phase of the events and use the keyup event.
35+
36+
<div class="example" markdown="1">
37+
$(document.documentElement).keyup(function (event) {
38+
// handle cursor keys
39+
});
40+
</div>
41+
42+
Note that all event handlers in jQuery, such as click, keyup, mouseover, etc receive an event [argument](http://en.wikipedia.org/wiki/Parameter_(computer_science)) - which I’ve captured under the variable name event.
43+
44+
The left and right key codes are 37 and 39 respectively. So we only want to action the slide if these keys are pressed, so we’ll check the keyCode property on the event - this property is [very well supported in browsers](http://www.quirksmode.org/js/keys.html):
45+
46+
<div class="example" markdown="1">
47+
$(document.documentElement).keyup(function (event) {
48+
// handle cursor keys
49+
if (event.keyCode == 37) {
50+
// go left
51+
} else if (event.keyCode == 39) {
52+
// go right
53+
}
54+
});
55+
</div>
56+
57+
##Triggering the Click on the Right Link
58+
59+
Triggering a click event is easy, but the problem we have to solve is finding the right link to click. Since this slider adds a class of current to the currently active link, we’ll use that as our anchor point, and try to find the link before (if the left cursor key is pressed) and after (if the right cursor key is pressed).
60+
61+
In some cases the current class might be on list element, which would make the navigating slightly easier, but in this case the markup looks a bit like this:
62+
63+
<div class="example" markdown="1">
64+
&lt;div class="coda-slider-wrapper"&gt;
65+
&lt;ul&gt;
66+
&lt;li&gt;&lt;a class="current" href="#1"&gt;1&lt;/a&gt;&lt;/li&gt;
67+
&lt;li&gt;&lt;a href="#2"&gt;2&lt;/a&gt;&lt;/li&gt;
68+
&lt;li&gt;&lt;a href="#3"&gt;3&lt;/a&gt;&lt;/li&gt;
69+
&lt;li&gt;&lt;a href="#4"&gt;4&lt;/a&gt;&lt;/li&gt;
70+
&lt;li&gt;&lt;a href="#5"&gt;5&lt;/a&gt;&lt;/li&gt;
71+
&lt;/ul&gt;
72+
&lt;/div&gt;
73+
</div>
74+
75+
In the case above, the “next” link is #2. Currently there’s no previous available, but we’ll let jQuery handle this for us.
76+
77+
To find the next link, first we need to grab the link that’s currently selected:
78+
79+
<div class="example" markdown="1">
80+
$('.coda-slider-wrapper ul a.current')
81+
</div>
82+
83+
Next we need to move up the tree (to the li element) and move to the next element and then back down to the a element to trigger a click.
84+
85+
<div class="example" markdown="1">
86+
$('.coda-slider-wrapper ul a.current')
87+
.parent() // moves up to the li element
88+
.next() // moves to the adjacent li element
89+
.find('a') // moves down to the link
90+
.click(); // triggers a click on the next link
91+
</div>
92+
93+
Since jQuery continues to allow chained methods to work even if there’s no elements found, we can also use prev() in the place of next() when current is on the first element and the code will work just fine still.
94+
95+
Let’s plug this code in to the keyboard event handler:
96+
97+
<div class="example" markdown="1">
98+
$(document.documentElement).keyup(function (event) {
99+
// handle cursor keys
100+
if (event.keyCode == 37) {
101+
// go left
102+
$('.coda-slider-wrapper ul a.current')
103+
.parent() // moves up to the li element
104+
.prev() // moves to the adjacent li element
105+
.find('a') // moves down to the link
106+
.click(); // triggers a click on the previous link
107+
} else if (event.keyCode == 39) {
108+
// go right
109+
// same as above, but just on one line and next instead of prev
110+
$('.coda-slider-wrapper ul a.current').parent().next().find('a').click();
111+
}
112+
});
113+
</div>
114+
115+
This code can be simplified since a lot of it is repetitive aside from the ‘next’ and ‘prev’. If you’re happy for slightly more complicated code, then use the code below, otherwise stick with the code above.
116+
117+
<div class="example" markdown="1">
118+
$(document.documentElement).keyup(function (event) {
119+
var direction = null;
120+
121+
// handle cursor keys
122+
if (event.keyCode == 37) {
123+
// go left
124+
direction = 'prev';
125+
} else if (event.keyCode == 39) {
126+
// go right
127+
direction = 'next';
128+
}
129+
130+
if (direction != null) {
131+
$('.coda-slider-wrapper ul a.current').parent()[direction]().find('a').click();
132+
}
133+
});
134+
</div>
135+
136+
##Where does this all go?
137+
138+
So we have our code, but where does it all fit together with the existing code?
139+
140+
Since we’re going in after the slider plugin is run, so it should go *directly after the plugin is initialised.
141+
142+
In Mathieu’s code, he had the following:
143+
144+
<div class="example" markdown="1">
145+
$().ready(function() {
146+
$('#coda-slider-1').codaSlider();
147+
});
148+
</div>
149+
150+
Note that $().ready is the same as $(document).ready (though it’s not a style I would personally use). *Directly* after the plugin (i.e. before the });) results in the following code:
151+
152+
<div class="example" markdown="1">
153+
$().ready(function() {
154+
$().ready(function() {
155+
$('#coda-slider-1').codaSlider();
156+
157+
$(document.documentElement).keyup(function (event) {
158+
var direction = null;
159+
160+
// handle cursor keys
161+
if (event.keyCode == 37) {
162+
// go left
163+
direction = 'prev';
164+
} else if (event.keyCode == 39) {
165+
// go right
166+
direction = 'next';
167+
}
168+
169+
if (direction != null) {
170+
$('.coda-slider-wrapper ul a.current').parent()[direction]().find('a').click();
171+
}
172+
});
173+
});
174+
</div>
175+
176+
You can see this all [in action in the demo](http://static.jqueryfordesigners.com/demo/keyboard-nav.html), and be sure to use the left and right keyboard cursor keys to see the demo working.
177+
178+
##Alternative uses
179+
180+
You can reuse this code for a lot of the sliders so long as there are links to navigate between the panels - you just need to navigate the DOM correctly to trigger the click on the right link based on the cursor key presses.

0 commit comments

Comments
 (0)