Merge branch 'MDL-51983-master' of git://github.com/ryanwyllie/moodle

This commit is contained in:
Andrew Nicols
2015-11-04 15:21:37 +08:00
6 changed files with 106 additions and 26 deletions
+29
View File
@@ -0,0 +1,29 @@
@core
Feature: Navigate action menu
In order to navigate an action menu
As a user
I need to be able to use the keyboard
@javascript
Scenario: The menu does not close on keyboard navigation
When I log in as "admin"
# Click to open the user menu.
And I click on ".usermenu a.toggle-display" "css_element" in the ".usermenu" "css_element"
# The menu should now be visible.
Then ".usermenu [role='menu']" "css_element" should be visible
# Press down arrow.
And I press key "40" in "#actionmenuaction-1" "css_element"
# The menu should still be visible.
And ".usermenu [role='menu']" "css_element" should be visible
@javascript
Scenario: The menu closes when it clicked outside
When I log in as "admin"
# Click to open the user menu.
And I click on ".usermenu a.toggle-display" "css_element" in the ".usermenu" "css_element"
# The menu should now be visible.
Then ".usermenu [role='menu']" "css_element" should be visible
# Click outside the menu.
And I click on "adminsearchquery" "field"
# The menu should now be hidden.
And ".usermenu [role='menu']" "css_element" should not be visible
+36
View File
@@ -1444,4 +1444,40 @@ class behat_general extends behat_base {
throw new ExpectationException('Unknown browser button.', $session);
}
}
/**
* Trigger a keydown event for a key on a specific element.
*
* @When /^I press key "(?P<key_string>(?:[^"]|\\")*)" in "(?P<element_string>(?:[^"]|\\")*)" "(?P<selector_string>[^"]*)"$/
* @param string $key either char-code or character itself,
* may optionally be prefixed with ctrl-, alt-, shift- or meta-
* @param string $element Element we look for
* @param string $selectortype The type of what we look for
* @throws DriverException
* @throws ExpectationException
*/
public function i_press_key_in_element($key, $element, $selectortype) {
if (!$this->running_javascript()) {
throw new DriverException('Key down step is not available with Javascript disabled');
}
// Gets the node based on the requested selector type and locator.
$node = $this->get_selected_node($selectortype, $element);
$modifier = null;
$validmodifiers = array('ctrl', 'alt', 'shift', 'meta');
$char = $key;
if (strpos($key, '-')) {
list($modifier, $char) = preg_split('/-/', $key, 2);
$modifier = strtolower($modifier);
if (!in_array($modifier, $validmodifiers)) {
throw new ExpectationException(sprintf('Unknown key modifier: %s.', $modifier));
}
}
if (is_numeric($char)) {
$char = (int)$char;
}
$node->keyDown($char, $modifier);
$node->keyPress($char, $modifier);
$node->keyUp($char, $modifier);
}
}
@@ -317,18 +317,22 @@ ACTIONMENU.prototype = {
*/
handleKeyboardEvent: function(e) {
var next;
var markEventHandled = function(e) {
e.preventDefault();
e.stopPropagation();
};
// Handle when the menu is still selected.
if (e.currentTarget.ancestor(SELECTOR.TOGGLE, true)) {
if ((e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) && this.firstMenuChild) {
this.firstMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 38 && this.lastMenuChild) {
this.lastMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 9 && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
}
return this;
}
@@ -336,11 +340,11 @@ ACTIONMENU.prototype = {
if (e.keyCode === 27) {
// The escape key was pressed so close the menu.
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 32) {
// The space bar was pressed. Trigger a click.
e.preventDefault();
markEventHandled(e);
e.currentTarget.simulate('click');
} else if (e.keyCode === 9) {
// The tab key was pressed. Tab moves forwards, Shift + Tab moves backwards through the menu options.
@@ -348,13 +352,14 @@ ACTIONMENU.prototype = {
// focus is moved to.
if (e.target === this.firstMenuChild && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.target === this.lastMenuChild && !e.shiftKey) {
if (this.hideMenu(e)) {
// Determine the next selector and focus on it.
next = this.menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
if (next) {
next.focus();
markEventHandled(e);
}
}
}
@@ -403,7 +408,7 @@ ACTIONMENU.prototype = {
if (next) {
next.focus();
e.preventDefault();
markEventHandled(e);
}
}
},
@@ -416,7 +421,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.ancestor(SELECTOR.MENUCHILD, true)) {
if (!e.target.ancestor(SELECTOR.MENUCONTENT, true)) {
this.hideMenu(e);
}
},
File diff suppressed because one or more lines are too long
@@ -315,18 +315,22 @@ ACTIONMENU.prototype = {
*/
handleKeyboardEvent: function(e) {
var next;
var markEventHandled = function(e) {
e.preventDefault();
e.stopPropagation();
};
// Handle when the menu is still selected.
if (e.currentTarget.ancestor(SELECTOR.TOGGLE, true)) {
if ((e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) && this.firstMenuChild) {
this.firstMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 38 && this.lastMenuChild) {
this.lastMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 9 && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
}
return this;
}
@@ -334,11 +338,11 @@ ACTIONMENU.prototype = {
if (e.keyCode === 27) {
// The escape key was pressed so close the menu.
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 32) {
// The space bar was pressed. Trigger a click.
e.preventDefault();
markEventHandled(e);
e.currentTarget.simulate('click');
} else if (e.keyCode === 9) {
// The tab key was pressed. Tab moves forwards, Shift + Tab moves backwards through the menu options.
@@ -346,13 +350,14 @@ ACTIONMENU.prototype = {
// focus is moved to.
if (e.target === this.firstMenuChild && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.target === this.lastMenuChild && !e.shiftKey) {
if (this.hideMenu(e)) {
// Determine the next selector and focus on it.
next = this.menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
if (next) {
next.focus();
markEventHandled(e);
}
}
}
@@ -400,7 +405,7 @@ ACTIONMENU.prototype = {
if (next) {
next.focus();
e.preventDefault();
markEventHandled(e);
}
}
},
@@ -413,7 +418,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.ancestor(SELECTOR.MENUCHILD, true)) {
if (!e.target.ancestor(SELECTOR.MENUCONTENT, true)) {
this.hideMenu(e);
}
},
+13 -8
View File
@@ -315,18 +315,22 @@ ACTIONMENU.prototype = {
*/
handleKeyboardEvent: function(e) {
var next;
var markEventHandled = function(e) {
e.preventDefault();
e.stopPropagation();
};
// Handle when the menu is still selected.
if (e.currentTarget.ancestor(SELECTOR.TOGGLE, true)) {
if ((e.keyCode === 40 || (e.keyCode === 9 && !e.shiftKey)) && this.firstMenuChild) {
this.firstMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 38 && this.lastMenuChild) {
this.lastMenuChild.focus();
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 9 && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
}
return this;
}
@@ -334,11 +338,11 @@ ACTIONMENU.prototype = {
if (e.keyCode === 27) {
// The escape key was pressed so close the menu.
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.keyCode === 32) {
// The space bar was pressed. Trigger a click.
e.preventDefault();
markEventHandled(e);
e.currentTarget.simulate('click');
} else if (e.keyCode === 9) {
// The tab key was pressed. Tab moves forwards, Shift + Tab moves backwards through the menu options.
@@ -346,13 +350,14 @@ ACTIONMENU.prototype = {
// focus is moved to.
if (e.target === this.firstMenuChild && e.shiftKey) {
this.hideMenu(e);
e.preventDefault();
markEventHandled(e);
} else if (e.target === this.lastMenuChild && !e.shiftKey) {
if (this.hideMenu(e)) {
// Determine the next selector and focus on it.
next = this.menulink.next(SELECTOR.CAN_RECEIVE_FOCUS_SELECTOR);
if (next) {
next.focus();
markEventHandled(e);
}
}
}
@@ -401,7 +406,7 @@ ACTIONMENU.prototype = {
if (next) {
next.focus();
e.preventDefault();
markEventHandled(e);
}
}
},
@@ -414,7 +419,7 @@ ACTIONMENU.prototype = {
* @param {EventFacade} e
*/
hideIfOutside : function(e) {
if (!e.target.ancestor(SELECTOR.MENUCHILD, true)) {
if (!e.target.ancestor(SELECTOR.MENUCONTENT, true)) {
this.hideMenu(e);
}
},