Skip to content

Commit 6b081e4

Browse files
author
Scott Bommarito
authored
Improve implementation of "Skip To Content" link (#6906)
1 parent 87f0f23 commit 6b081e4

1 file changed

Lines changed: 33 additions & 61 deletions

File tree

src/NuGetGallery/Scripts/gallery/common.js

Lines changed: 33 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -208,72 +208,40 @@
208208
nuget.configureFileInputButton = function (id) {
209209
// File input buttons should respond to keyboard events.
210210
$("#" + id).on("keypress", function (e) {
211-
var code = (e.keyCode || e.which);
212-
var isInteract = (code == 13 /*enter*/ || code == 32 /*space*/) && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
211+
var code = e.keyCode || e.which;
212+
var isInteract = (code === 13 /*enter*/ || code === 32 /*space*/) && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey;
213213
if (isInteract) {
214214
$(this).click();
215215
}
216216
});
217-
}
218-
219-
nuget.canElementBeTabbedTo = function (element) {
220-
var isElement = function (type) {
221-
return element.is(type);
222-
}
223-
224-
var hasAttribute = function (attributeName) {
225-
var attribute = element.attr(attributeName);
226-
return typeof attribute !== typeof undefined && attribute !== false;
227-
}
217+
};
228218

229-
if (hasAttribute("tabindex")) {
230-
// Elements that have had their tabindex set to -1 cannot be tabbed to.
231-
return element.attr("tabindex") !== "-1";
219+
nuget.canElementBeFocused = function (element) {
220+
element = $(element);
221+
if (!element.is(':visible')) {
222+
return false;
232223
}
233224

234225
// See https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Interactive_content
235226
var alwaysInteractiveElements = ['a', 'button', 'details', 'embed', 'iframe', 'keygen', 'label', 'select', 'textarea'];
236227
var i;
237228
for (i = 0; i < alwaysInteractiveElements.length; i++) {
238-
if (isElement(alwaysInteractiveElements[i])) {
229+
if (element.is(alwaysInteractiveElements[i])) {
239230
return true;
240231
}
241232
}
242233

243-
return ((isElement("audio") && hasAttribute("controls")) ||
244-
(isElement("img") && hasAttribute("usemap")) ||
245-
(isElement("input") && element.attr("type") !== "hidden") ||
246-
(isElement("menu") && element.attr("type") !== "toolbar") ||
247-
(isElement("object") && hasAttribute("usemap")) ||
248-
(isElement("video") && hasAttribute("controls")));
249-
}
250-
251-
nuget.getFirstChildThatCanBeTabbedTo = function (element) {
252-
if (window.nuget.canElementBeTabbedTo(element)) {
253-
return element;
254-
}
255-
256-
// If an element has its tabindex set to -1, none of its children can be tabbed to.
257-
if (element.attr("tabindex") === "-1") {
258-
return null;
259-
}
260-
261-
var i;
262-
var children = element.children();
263-
for (i = 0; i < children.length; i++) {
264-
var child = children.eq(i);
265-
if (window.nuget.canElementBeTabbedTo(child)) {
266-
return child;
267-
}
268-
269-
var childChild = window.nuget.getFirstChildThatCanBeTabbedTo(child);
270-
if (childChild !== null) {
271-
return childChild;
272-
}
273-
}
234+
return element.is("audio") && !!element.attr("controls") ||
235+
element.is("img") && !!element.attr("usemap") ||
236+
element.is("input") && element.attr("type") !== "hidden" ||
237+
element.is("menu") && element.attr("type") !== "toolbar" ||
238+
element.is("object") && !!element.attr("usemap") ||
239+
element.is("video") && !!element.attr("controls");
240+
};
274241

275-
return null;
276-
}
242+
nuget.canElementBeTabbedTo = function (element) {
243+
return window.nuget.canElementBeFocused(element) && $(element).attr('tabindex') !== "-1";
244+
};
277245

278246
// Source: https://stackoverflow.com/a/27568129/52749
279247
// Detects whether SVG is supported in the browser.
@@ -365,7 +333,7 @@
365333
var $field = $("#AntiForgeryForm input[name=__RequestVerificationToken]");
366334
if (data instanceof FormData)
367335
{
368-
data.append($tokenKey, $field.val())
336+
data.append($tokenKey, $field.val());
369337
}
370338
else
371339
{
@@ -383,10 +351,15 @@
383351
}
384352

385353
return stringToFormat;
386-
}
354+
};
387355

388356
window.nuget = nuget;
389357

358+
jQuery.extend(jQuery.expr[':'], {
359+
focusable: window.nuget.canElementBeFocused,
360+
tabbable: window.nuget.canElementBeTabbedTo
361+
});
362+
390363
initializeJQueryValidator();
391364

392365
$(function () {
@@ -454,16 +427,16 @@
454427
});
455428

456429
$(document).on('keydown', function (e) {
457-
var code = (e.keyCode || e.which);
430+
var code = e.keyCode || e.which;
458431
var isValidInputCharacter =
459-
((code >= 48 && code <= 57) // numbers 0-9
460-
|| (code >= 64 && code <= 90) // letters a-z
461-
|| (code >= 96 && code <= 111) // numpad
462-
|| (code >= 186 && code <= 192) // ; = , - . / `
463-
|| (code >= 219 && code <= 222)) // [\ ] '
432+
(code >= 48 && code <= 57 // numbers 0-9
433+
|| code >= 64 && code <= 90 // letters a-z
434+
|| code >= 96 && code <= 111 // numpad
435+
|| code >= 186 && code <= 192 // ; = , - . / `
436+
|| code >= 219 && code <= 222) // [\ ] '
464437
&& !e.altKey && !e.ctrlKey && !e.metaKey;
465438

466-
if (isValidInputCharacter && document.activeElement == document.body) {
439+
if (isValidInputCharacter && document.activeElement === document.body) {
467440
var searchbox = $("#search");
468441
searchbox.focus();
469442
var currInput = searchbox.val();
@@ -475,7 +448,7 @@
475448
$("#skipToContent").on('click', function () {
476449
// Focus on the first element that can be tabbed to inside the "skippedToContent" element.
477450
var skippedToContent = $("#skippedToContent");
478-
var firstChildThatCanBeTabbedTo = window.nuget.getFirstChildThatCanBeTabbedTo(skippedToContent.first());
451+
var firstChildThatCanBeTabbedTo = skippedToContent.find(':tabbable').first();
479452
if (firstChildThatCanBeTabbedTo !== null) {
480453
firstChildThatCanBeTabbedTo.focus();
481454
} else {
@@ -486,4 +459,3 @@
486459
});
487460
});
488461
}());
489-

0 commit comments

Comments
 (0)