|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <!-- |
|
4 https://bugzilla.mozilla.org/show_bug.cgi?id=409604 |
|
5 --> |
|
6 <head> |
|
7 <title>Test for Bug 409604</title> |
|
8 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
9 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
|
10 </head> |
|
11 <body id="body"> |
|
12 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=409604">Mozilla Bug 409604</a> |
|
13 <p id="display"></p> |
|
14 <div id="content" style="display: none"> |
|
15 |
|
16 </div> |
|
17 <pre id="test"> |
|
18 <script class="testbody" type="text/javascript"> |
|
19 |
|
20 /** Test for Bug 409604 **/ |
|
21 |
|
22 var modifier = SpecialPowers.Ci.nsIDOMEvent.ALT_MASK | |
|
23 SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK; |
|
24 var expectedFocus = "a,c,d,e,f,g,h,i,j,k,l,m,n,p,x,y"; |
|
25 // XXX the "map" test is causing trouble, see bug 433089 |
|
26 var focusArray = expectedFocus.split(","); |
|
27 var unfocusableElementId = "invalid"; |
|
28 var unfocusableTags = [ |
|
29 {tag: "abbr", content: "text", attribs: {title: "something"}}, |
|
30 {tag: "acronym", content: "text", attribs: {title: "something"}}, |
|
31 {tag: "address", content: "text"}, |
|
32 {tag: "b", content: "text"}, |
|
33 {tag: "bdo", content: "text"}, |
|
34 {tag: "big", content: "text"}, |
|
35 {tag: "blockquote", content: "text"}, |
|
36 {tag: "caption", content: "text", parent: "table", where: "first"}, |
|
37 {tag: "cite", content: "text"}, |
|
38 {tag: "code", content: "text"}, |
|
39 {tag: "dd", content: "text", parent: "dl"}, |
|
40 {tag: "del", content: "text"}, |
|
41 {tag: "dfn", content: "text", attribs: {title: "something"}}, |
|
42 {tag: "div", content: "text"}, |
|
43 {tag: "dl", content: "<dd>text</dd>", parent: "dl"}, |
|
44 {tag: "dt", content: "text", parent: "dl"}, |
|
45 {tag: "em", content: "text"}, |
|
46 {tag: "fieldset", content: "text"}, |
|
47 {tag: "form", content: "text", attribs: {action: "any.html"}}, |
|
48 {tag: "h1", content: "text"}, |
|
49 {tag: "h2", content: "text"}, |
|
50 {tag: "h3", content: "text"}, |
|
51 {tag: "h4", content: "text"}, |
|
52 {tag: "h5", content: "text"}, |
|
53 {tag: "h6", content: "text"}, |
|
54 {tag: "hr"}, |
|
55 {tag: "i", content: "text"}, |
|
56 {tag: "img", attribs: {src: "any.png", alt: "image"}}, |
|
57 {tag: "ins", content: "text"}, |
|
58 {tag: "kbd", content: "text"}, |
|
59 {tag: "li", content: "text", parent: "ol"}, |
|
60 {tag: "li", content: "text", parent: "ul"}, |
|
61 {tag: "noscript", content: "text"}, |
|
62 {tag: "ol", content: "<li>text</li>"}, |
|
63 {tag: "optgroup", content: "<option>text</option>", attribs: {label: "some label"}, parent: "select"}, |
|
64 {tag: "option", content: "text", parent: "select"}, |
|
65 {tag: "p", content: "text"}, |
|
66 {tag: "pre", content: "text"}, |
|
67 {tag: "q", content: "text"}, |
|
68 {tag: "samp", content: "text"}, |
|
69 {tag: "small", content: "text"}, |
|
70 {tag: "span", content: "text"}, |
|
71 {tag: "strong", content: "text"}, |
|
72 {tag: "sub", content: "text"}, |
|
73 {tag: "sup", content: "text"}, |
|
74 {tag: "tt", content: "text"}, |
|
75 {tag: "ul", content: "<li>text</li>"}, |
|
76 {tag: "var", content: "text"} |
|
77 ]; |
|
78 var invalidElements = [ |
|
79 "body", |
|
80 "col", |
|
81 "colgroup", |
|
82 // XXX the "map" test is causing trouble, see bug 433089 |
|
83 // "map", |
|
84 "table", |
|
85 "tbody", |
|
86 "td", |
|
87 "tfoot", |
|
88 "th", |
|
89 "thead", |
|
90 "tr" |
|
91 ]; |
|
92 |
|
93 // ui.key.contentAccess must be set to value 5 before running the test. |
|
94 function setOrRestoreContentAccess(newValue) { |
|
95 if (!newValue) { |
|
96 SpecialPowers.clearUserPref("ui.key.contentAccess"); |
|
97 } else { |
|
98 SpecialPowers.setIntPref("ui.key.contentAccess", newValue); |
|
99 } |
|
100 } |
|
101 |
|
102 function handleFocus(e) { |
|
103 ok("accessKey" in e, "(focus) accesskey property not found on element"); |
|
104 var expected = focusArray.shift(); |
|
105 // "k" and "n" are a special cases because the element receiving the focus |
|
106 // is not the element which has the accesskey. |
|
107 if (expected == "k" || expected == "n") { |
|
108 ok(e.value == "test for label", "(focus) unexpected element: " + e.value + |
|
109 " expected: " + "test for label"); |
|
110 // "l" is a special case because the element receiving the focus is not |
|
111 // the element which has the accesskey. |
|
112 } else if (expected == "l") { |
|
113 ok(e.value == "test for legend", "(focus) unexpected element: " + e.value + |
|
114 " expected: " + "test for legend"); |
|
115 } else { |
|
116 ok(expected == e.accessKey, "(focus) unexpected element: " + e.accessKey + |
|
117 " expected: " + expected); |
|
118 } |
|
119 } |
|
120 |
|
121 function handleClick(e) { |
|
122 ok("accessKey" in e, "(click) accesskey property not found on element"); |
|
123 } |
|
124 |
|
125 function handleInvalid(e) { |
|
126 ok("accessKey" in e, "(invalid) accesskey property not found on element"); |
|
127 ok(false, "(invalid) accesskey should not have any effect on this element: " + |
|
128 e.localName); |
|
129 } |
|
130 |
|
131 function pressAccessKey(key) { |
|
132 var utils = SpecialPowers.DOMWindowUtils; |
|
133 utils.sendKeyEvent("keydown", key, key, modifier); |
|
134 utils.sendKeyEvent("keypress", key, key, modifier); |
|
135 utils.sendKeyEvent("keyup", key, key, modifier); |
|
136 } |
|
137 |
|
138 function testFocusableElements() { |
|
139 for (var code = "a".charCodeAt(0); code <= "y".charCodeAt(0); ++ code) { |
|
140 // XXX the "map" test is causing trouble, see bug 433089 |
|
141 if (code == "b".charCodeAt(0)) |
|
142 continue; |
|
143 pressAccessKey(code); |
|
144 } |
|
145 ok(focusArray.length == 0, "(focus) unhandled elements remaining: " + focusArray.join(",")); |
|
146 } |
|
147 |
|
148 function createUnfocusableElement(elem, accesskey) { |
|
149 ok("tag" in elem, "invalid object passed to createUnfocusableElement: " + elem.toString()); |
|
150 var e = document.createElement(elem.tag); |
|
151 if ("content" in elem) { |
|
152 e.innerHTML = elem.content; |
|
153 } |
|
154 if ("attribs" in elem) { |
|
155 for (var attr in elem.attribs) { |
|
156 e.setAttribute(attr, elem.attribs[attr]); |
|
157 } |
|
158 } |
|
159 e.setAttribute("accesskey", accesskey); |
|
160 e.setAttribute("onclick", "handleClick(event.target); event.preventDefault();"); |
|
161 e.setAttribute("onfocus", "handleInvalid(event.target);"); |
|
162 var parent = null; |
|
163 var elementToInsert = null; |
|
164 if ("parent" in elem) { |
|
165 parent = document.getElementById(elem.parent); |
|
166 elementToInsert = e; |
|
167 } else { |
|
168 parent = document.getElementById("tbody"); |
|
169 elementToInsert = document.createElement("tr"); |
|
170 var td = document.createElement("td"); |
|
171 td.textContent = elem.tag; |
|
172 elementToInsert.appendChild(td); |
|
173 td = document.createElement("td"); |
|
174 td.appendChild(e); |
|
175 elementToInsert.appendChild(td); |
|
176 } |
|
177 ok(parent != null, "parent element not specified for element: " + elem.tag); |
|
178 ok(elementToInsert != null, "elementToInsert not specified for element: " + elem.tag); |
|
179 elementToInsert.setAttribute("id", unfocusableElementId); |
|
180 if ("where" in elem) { |
|
181 if (elem.where == "first") { |
|
182 parent.insertBefore(elementToInsert, parent.firstChild); |
|
183 } else { |
|
184 ok(false, "invalid where value specified for element: " + elem.tag); |
|
185 } |
|
186 } else { |
|
187 parent.appendChild(elementToInsert); |
|
188 } |
|
189 } |
|
190 |
|
191 function destroyUnfocusableElement() { |
|
192 var el = document.getElementById(unfocusableElementId); |
|
193 ok(el != null, "unfocusable element not found"); |
|
194 el.parentNode.removeChild(el); |
|
195 ok(document.getElementById(unfocusableElementId) == null, "unfocusable element not properly removed"); |
|
196 } |
|
197 |
|
198 function testUnfocusableElements() { |
|
199 var i, e; |
|
200 for (i = 0; i < unfocusableTags.length; ++ i) { |
|
201 createUnfocusableElement(unfocusableTags[i], "z"); |
|
202 pressAccessKey("z".charCodeAt(0)); |
|
203 destroyUnfocusableElement(); |
|
204 } |
|
205 for (i = 0; i < invalidElements.length; ++ i) { |
|
206 e = document.getElementById(invalidElements[i]); |
|
207 ok(e != null, "element with ID " + invalidElements[i] + " not found"); |
|
208 e.setAttribute("accesskey", "z"); |
|
209 e.setAttribute("onclick", "handleClick(event.target); event.preventDefault();"); |
|
210 e.setAttribute("onfocus", "handleInvalid(event.target);"); |
|
211 pressAccessKey("z".charCodeAt(0)); |
|
212 e.removeAttribute("accesskey"); |
|
213 e.removeAttribute("onclick"); |
|
214 e.removeAttribute("onfocus"); |
|
215 } |
|
216 } |
|
217 |
|
218 function start() { |
|
219 testFocusableElements(); |
|
220 testUnfocusableElements(); |
|
221 setOrRestoreContentAccess(0); |
|
222 SimpleTest.finish(); |
|
223 } |
|
224 |
|
225 function doTest() { |
|
226 setOrRestoreContentAccess(5); |
|
227 setTimeout(start, 100); |
|
228 } |
|
229 |
|
230 SimpleTest.waitForExplicitFinish(); |
|
231 addLoadEvent(doTest); |
|
232 |
|
233 </script> |
|
234 </pre> |
|
235 <table id="table"> |
|
236 <thead id="thead"> |
|
237 <tr id="tr"><th id="th">Test header</th><th></th></tr> |
|
238 </thead> |
|
239 <tfoot id="tfoot"> |
|
240 <tr><td id="td">Test footer</td><td></td></tr> |
|
241 </tfoot> |
|
242 <tbody id="tbody"> |
|
243 <colgroup id="colgroup"> |
|
244 <col id="col"></col> |
|
245 <col></col> |
|
246 </colgroup> |
|
247 <tr> |
|
248 <td>a</td><td><a href="#" onclick="handleClick(event.target); return false;" accesskey="a" onfocus="handleFocus(event.target);">test link"</a></td> |
|
249 </tr> |
|
250 <!-- the "map" test is causing trouble, see bug 433089 |
|
251 <tr> |
|
252 <td>area</td><td><img src="about:logo" width="300" height="236" usemap="#map"> |
|
253 <map id="map" name="map"><area shape="rect" coords="0,0,82,126" href="#" |
|
254 onclick="handleClick(event.target); return false;" accesskey="b"></map> |
|
255 </td> |
|
256 </tr> |
|
257 --> |
|
258 <tr> |
|
259 <td>button</td><td><button onclick="handleClick(event.target);" accesskey="c" onfocus="handleFocus(event.target);">test button"</button></td> |
|
260 </tr> |
|
261 <tr> |
|
262 <td>input type="text"</td><td><input type="text" value="" onclick="handleClick(event.target);" onfocus="handleFocus(event.target);" accesskey="d"></td> |
|
263 </tr> |
|
264 <tr> |
|
265 <td>input type="button"</td><td><input type="button" value="type='button'" onclick="handleClick(event.target);" onfocus="handleFocus(event.target);" accesskey="e"></td> |
|
266 </tr> |
|
267 <tr> |
|
268 <td>input type="checkbox"</td><td><input type="checkbox" onclick="handleClick(event.target);" onfocus="handleFocus(event.target)" accesskey="f"></td> |
|
269 </tr> |
|
270 <tr> |
|
271 <td>input type="radio"</td><td><input type="radio" name="radio" onclick="handleClick(event.target);" onfocus="handleFocus(event.target);" accesskey="g"></td> |
|
272 </tr> |
|
273 <tr> |
|
274 <td>input type="password"</td><td><input type="password" onclick="handleClick(event.target);" onfocus="handleFocus(event.target);" accesskey="h"></td> |
|
275 </tr> |
|
276 <tr> |
|
277 <td>input type="submit"</td><td><input type="submit" value="type='submit'" onclick="handleClick(event.target); return false;" |
|
278 onfocus="handleFocus(event.target);" accesskey="i"></td> |
|
279 </tr> |
|
280 <tr> |
|
281 <td>input type="reset"</td><td><input type="submit" value="type='reset'" onclick="handleClick(event.target);" |
|
282 onfocus="handleFocus(event.target);" accesskey="j"></td> |
|
283 </tr> |
|
284 <tr> |
|
285 <td>label</td><td><label accesskey="k" onclick="handleClick(event.target);" onfocus="handleInvalid(event.target);">test label |
|
286 <input type="text" value="test for label" onfocus="handleFocus(event.target);" onclick="handleClick(event.target);"></label></td> |
|
287 </tr> |
|
288 <tr> |
|
289 <td>legend</td><td><fieldset><legend accesskey="l">test legend</legend> |
|
290 <input type="text" value="test for legend" onfocus="handleFocus(event.target);" onclick="handleClick(event.target);" ></fieldset></td> |
|
291 </tr> |
|
292 <tr> |
|
293 <td>textarea</td><td><textarea onfocus="handleFocus(event.target);" onclick="handleClick(event.target);" accesskey="m">test text</textarea></td> |
|
294 </tr> |
|
295 <tr> |
|
296 <td>label (label invisible)</td><td><label for="txt1" accesskey="n" style="display:none" |
|
297 onclick="handleClick(event.target);" onfocus="handleInvalid(event.target);">test label</label> |
|
298 <input type="text" id="txt1" value="test for label" onclick="handleClick(event.target);" onfocus="handleFocus(event.target);"></td> |
|
299 </tr> |
|
300 <tr> |
|
301 <td>label (control invisible)</td><td><label for="txt2" accesskey="o" |
|
302 onclick="handleClick(event.target);" onfocus="handleInvalid(event.target);">test label</label> |
|
303 <input type="text" id="txt2" value="test for label" onclick="handleClick(event.target);" |
|
304 onfocus="handleInvalid(event.target);" style="display:none"></td> |
|
305 </tr> |
|
306 <tr> |
|
307 <td>select</td> |
|
308 <td> |
|
309 <select onclick="handleClick(event.target);" onfocus="handleFocus(event.target)" accesskey="p"><option>option</option></select> |
|
310 </td> |
|
311 </tr> |
|
312 <tr> |
|
313 <td>object</td> |
|
314 <td> |
|
315 <object onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="q">an object</object> |
|
316 </td> |
|
317 </tr> |
|
318 <tr> |
|
319 <td>a without href</td> |
|
320 <td> |
|
321 <a onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="r">an object</object> |
|
322 </td> |
|
323 </tr> |
|
324 <tr> |
|
325 <td>disabled button</td> |
|
326 <td> |
|
327 <button disabled="" onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="s">disabled</button> |
|
328 </td> |
|
329 </tr> |
|
330 <tr> |
|
331 <td>disabled input</td> |
|
332 <td> |
|
333 <input disabled="" onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="t"></input> |
|
334 </td> |
|
335 </tr> |
|
336 <tr> |
|
337 <td>hidden input</td> |
|
338 <td> |
|
339 <input type="hidden" onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="u">disabled</input> |
|
340 </td> |
|
341 </tr> |
|
342 <tr> |
|
343 <td>disabled select</td> |
|
344 <td> |
|
345 <select disabled onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="v"> |
|
346 <option>disabled</option> |
|
347 </select> |
|
348 </td> |
|
349 </tr> |
|
350 <tr> |
|
351 <td>disabled textarea</td> |
|
352 <td> |
|
353 <textarea disabled onclick="handleClick(event.target);" onfocus="handleInvalid(event.target)" accesskey="w">disabled</textarea> |
|
354 </td> |
|
355 </tr> |
|
356 <tr> |
|
357 <td>scrollable div(focusable)</td> |
|
358 <td> |
|
359 <div onclick="handleClick(event.target);" onfocus="handleFocus(event.target)" accesskey="x" style="height: 50px; overflow: auto;"> |
|
360 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy |
|
361 |
|
362 dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the |
|
363 |
|
364 lazy dog. The quick brown fox jumps over the lazy dog. |
|
365 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy |
|
366 |
|
367 dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the |
|
368 |
|
369 lazy dog. The quick brown fox jumps over the lazy dog. |
|
370 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy |
|
371 |
|
372 dog. The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the |
|
373 |
|
374 lazy dog. The quick brown fox jumps over the lazy dog. |
|
375 </div> |
|
376 </td> |
|
377 </tr> |
|
378 <tr> |
|
379 <td>contenteditable div(focusable)</td> |
|
380 <td> |
|
381 <div onclick="handleClick(event.target);" onfocus="handleFocus(event.target)" accesskey="y" contenteditable="true"> |
|
382 Test text..... |
|
383 </div> |
|
384 </td> |
|
385 </tr> |
|
386 </tbody> |
|
387 </table> |
|
388 <dl id="dl"></dl> |
|
389 <ul id="ul"></ul> |
|
390 <ol id="ol"></ol> |
|
391 <select id="select"></select> |
|
392 </body> |
|
393 </html> |