diff --git a/common/test/acceptance/tests/lms/test_account_settings.py b/common/test/acceptance/tests/lms/test_account_settings.py
index f6f935d301..ede578d60e 100644
--- a/common/test/acceptance/tests/lms/test_account_settings.py
+++ b/common/test/acceptance/tests/lms/test_account_settings.py
@@ -461,7 +461,7 @@ class AccountSettingsA11yTest(AccountSettingsTestMixin, WebAppTest):
self.visit_account_settings_page()
self.account_settings_page.a11y_audit.config.set_rules({
'ignore': [
- 'link-href', # TODO: AC-233, AC-238
+ 'link-href', # TODO: AC-233
],
})
self.account_settings_page.a11y_audit.check_for_accessibility_errors()
diff --git a/common/test/acceptance/tests/lms/test_lms_dashboard.py b/common/test/acceptance/tests/lms/test_lms_dashboard.py
index ab81dfd3f2..6269f3af71 100644
--- a/common/test/acceptance/tests/lms/test_lms_dashboard.py
+++ b/common/test/acceptance/tests/lms/test_lms_dashboard.py
@@ -232,11 +232,4 @@ class LmsDashboardA11yTest(BaseLmsDashboardTest):
"""
course_listings = self.dashboard_page.get_course_listings()
self.assertEqual(len(course_listings), 1)
-
- self.dashboard_page.a11y_audit.config.set_rules({
- "ignore": [
- 'link-href', # TODO: AC-238
- ],
- })
-
self.dashboard_page.a11y_audit.check_for_accessibility_errors()
diff --git a/lms/static/js/dashboard/dropdown.js b/lms/static/js/dashboard/dropdown.js
new file mode 100644
index 0000000000..d310fb3220
--- /dev/null
+++ b/lms/static/js/dashboard/dropdown.js
@@ -0,0 +1,90 @@
+var edx = edx || {};
+
+(function ($) {
+ 'use strict';
+
+ edx.dashboard = edx.dashboard || {};
+ edx.dashboard.dropdown = {};
+
+ // Generate the properties object to be passed along with business intelligence events.
+ edx.dashboard.dropdown.toggleCourseActionsDropdownMenu = function (event) {
+ // define variables for code legibility
+ var dashboardIndex = $(event.currentTarget).data().dashboardIndex,
+ dropdown = $('#actions-dropdown-' + dashboardIndex),
+ dropdownButton = $('#actions-dropdown-link-' + dashboardIndex),
+ ariaExpandedState = (dropdownButton.attr('aria-expanded') === 'true'),
+ menuItems = dropdown.find('a');
+
+ var catchKeyPress = function(object, event) {
+ // get currently focused item
+ var focusedItem = $(':focus');
+
+ // get the index of the currently focused item
+ var focusedItemIndex = menuItems.index(focusedItem);
+
+ // var to store next focused item index
+ var itemToFocusIndex;
+
+ // if space or escape key pressed
+ if ( event.which === 32 || event.which === 27) {
+ dropdownButton.click();
+ event.preventDefault();
+ }
+
+ // if up arrow key pressed or shift+tab
+ else if (event.which === 38 || (event.which === 9 && event.shiftKey)) {
+ // if first item go to last
+ if (focusedItemIndex === 0 || focusedItemIndex === -1) {
+ menuItems.last().focus();
+ } else {
+ itemToFocusIndex = focusedItemIndex - 1;
+ menuItems.get(itemToFocusIndex).focus();
+ }
+ event.preventDefault();
+ }
+
+ // if down arrow key pressed or tab key
+ else if (event.which === 40 || event.which === 9) {
+ // if last item go to first
+ if (focusedItemIndex === menuItems.length - 1 || focusedItemIndex === -1) {
+ menuItems.first().focus();
+ } else {
+ itemToFocusIndex = focusedItemIndex + 1;
+ menuItems.get(itemToFocusIndex).focus();
+ }
+ event.preventDefault();
+ }
+ };
+
+ // Toggle the visibility control for the selected element and set the focus
+ dropdown.toggleClass('is-visible');
+ if (dropdown.hasClass('is-visible')) {
+ dropdown.attr('tabindex', -1);
+ dropdown.focus();
+ } else {
+ dropdown.removeAttr('tabindex');
+ dropdownButton.focus();
+ }
+
+ // Inform the ARIA framework that the dropdown has been expanded
+ dropdownButton.attr('aria-expanded', !ariaExpandedState);
+
+ //catch keypresses when inside dropdownMenu (we want to catch spacebar;
+ // escape; up arrow or shift+tab; and down arrow or tab)
+ dropdown.on('keydown', function(event){
+ catchKeyPress($(this), event);
+ });
+ };
+
+ edx.dashboard.dropdown.bindToggleButtons = function() {
+ $('.action-more').bind(
+ 'click',
+ edx.dashboard.dropdown.toggleCourseActionsDropdownMenu
+ );
+ };
+
+ $(document).ready(function() {
+ edx.dashboard.dropdown.bindToggleButtons();
+ });
+
+})(jQuery);
diff --git a/lms/static/js/dashboard/legacy.js b/lms/static/js/dashboard/legacy.js
index 050f2a493f..5438475a84 100644
--- a/lms/static/js/dashboard/legacy.js
+++ b/lms/static/js/dashboard/legacy.js
@@ -37,8 +37,6 @@
notifications.focus();
}
- $('.action-more').bind('click', toggleCourseActionsDropdown);
-
// Track clicks of the upgrade button. The `trackLink` method is a helper that makes
// a `track` call whenever a bound link is clicked. Usually the page would change before
// `track` had time to execute; `trackLink` inserts a small timeout to give the `track`
@@ -79,33 +77,6 @@
return properties;
}
- function toggleCourseActionsDropdownInternal(element) {
- var dashboard_index = element.data('dashboard-index');
-
- // Toggle the visibility control for the selected element and set the focus
- var dropdown_selector = 'div#actions-dropdown-' + dashboard_index;
- var dropdown = $(dropdown_selector);
- dropdown.toggleClass('is-visible');
- if (dropdown.hasClass('is-visible')) {
- dropdown.attr('tabindex', -1);
- } else {
- dropdown.removeAttr('tabindex');
- }
-
- // Inform the ARIA framework that the dropdown has been expanded
- var anchor_selector = 'a#actions-dropdown-link-' + dashboard_index;
- var anchor = $(anchor_selector);
- var aria_expanded_state = (anchor.attr('aria-expanded') === 'true');
- anchor.attr('aria-expanded', !aria_expanded_state);
- }
-
- function toggleCourseActionsDropdown(event) {
- toggleCourseActionsDropdownInternal($(this));
-
- // Suppress the actual click event from the browser
- event.preventDefault();
- }
-
$("#failed-verification-button-dismiss").click(function() {
$.ajax({
url: urls.verifyToggleBannerFailedOff,
@@ -128,7 +99,7 @@
if($(event.target).data("optout") === "False") {
$("#receive_emails").prop('checked', true);
}
- toggleCourseActionsDropdownInternal(element);
+ edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
$(".action-unenroll").click(function(event) {
@@ -144,7 +115,7 @@
}, true));
$('#refund-info').html( element.data("refund-info") );
$("#unenroll_course_id").val( element.data("course-id") );
- toggleCourseActionsDropdownInternal(element);
+ edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
$('#unenroll_form').on('ajax:complete', function(event, xhr) {
@@ -179,7 +150,6 @@
return false;
});
-
$(".action-email-settings").each(function(index){
$(this).attr("id", "email-settings-" + index);
// a bit of a hack, but gets the unique selector for the modal trigger
diff --git a/lms/static/js/fixtures/dashboard/dashboard.html b/lms/static/js/fixtures/dashboard/dashboard.html
index 07c5c00a0e..b83627523d 100644
--- a/lms/static/js/fixtures/dashboard/dashboard.html
+++ b/lms/static/js/fixtures/dashboard/dashboard.html
@@ -1,3 +1,7 @@
+
@@ -21,12 +25,13 @@
+