-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Menubar: move to next item applied focus() to too many items #953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thanks, can you add a unit test showing the behavior? Also, this new selector is unnecessarily duplicative. I haven't reviewed menubar yet, but this is pointing out a pretty big problem to me. Menubar cannot use button's classes without a dependency on button. |
My feeling on menubar at the moment is that its entire construction is flawed. It's built like a giant piece of DOM that responds to events instead of a series of encapsulating widgets. I'm of the opinion that there should be better abstractions in place: yes there should be a menubar widget but also a menubarItem widget (using $.Widget) and a submenu widget, and probably others. There's considerable mental pain and hidden bugs in the current design (which, yes, I had a hand in). I feel like this could be a whole lot less buggy if it were to be designed this way. Am I opening an unholy can of worms? Or should widgets not depend on other widgets? I personally think that would be a whole lot simpler (to say nothing of infinitely easier to test). |
Menubar actually uses the menu widget, so its not entirely monolithic. So we're generally open to composing widgets of other widgets. If further splits would actually help here remains to be seen. Is that something you're interested in prototyping? In general considering the complexity of menu itself its not suprising that menubar ends up even more complex. The combination of mouse and keyboard handling, while managing focus, just leads to that. I'm not sure if further decomposition can really make a positive difference. |
I am strongly opposed to the addition of a menubaritem widget. |
I also agree that a menubaritem widget is not a good idea. |
@jzaefferer It's reassuring that you see that menubar will be an increment of weirdness around menu. Others: will not create a new widget. @scottgonzalez Will create test case All: Finishing up the top two bugs at http://wiki.jqueryui.com/w/page/38666403/Menubar. |
@scottgonzalez Changes made, tests provided. I should be more wary when writing code before work 🌔 . |
@jzaefferer Where does this leave things in terms of http://wiki.jqueryui.com/w/page/38666403/Menubar ? If this is squared away, I can move to "Disable items/menus with class="ui-state-disabled" " |
@kborchers and @scottgonzalez I know you both were against the idea of creating a new widget but... I have this PR: #958 where I show what happened when I played with the idea. I think the code is much better for it, but I would really like a way to:
If you could take a look at that PR and see if there's anything good about it that can be brought over, or tell me how to implement a private widget, I think this code would be the better for it. |
|
Can do these top 3 today. Writing more test suite will need to be ongoing. |
`_move` was believed to specify just one item, called `focusableTarget`. Using the broader selectors this would return anything matching `a` or `button`. This means that the next item _as well as_ any `button`s or `a`s found thereunder would _also_ have their focus() event fired.
1. Load page 1. Tab to first bar 1. Right cursor 1. Down cursor 1. Right cursor 1. Error Test the object that is tested for an `active` for definition before querying that property. Create new method for assessing whether or not a new submenu should be opened. The testing here is a smell. This logic should be simplified.
Closing. Will re-open when I have more tests. |
Is there a test I can crib from which tests TAB and shift-TAB behavior? I want to provide the |
jquery-ui/tests/unit/dialog/dialog_core.js Line 119 in 71a332e
|
Per your comments of 2013-04-16
These two specific bugs have been addressed. I've attempted to break things manually but have not been able to produce any other cursor key or TAB-order bugs.
Commit 4e47df2 brings in unit testing for some of the basics of this but, per its commit message, I don't see why my invocations are failing as the demo works and my other uses of
My goal would be now to move to this phase of things with focus on getting the unit tests in place. I suspect I can mutate this code to look a great deal more like |
@scottgonzalez Removed junk you pointed out in meeting today. |
@@ -46,4 +46,76 @@ test( "hover over a menu item with no sub-menu should close open menu", function | |||
equal($(".ui-menu:visible").length, 0, "After triggering a sub-menu, a click on a peer menu item should close the opened sub-menu"); | |||
}); | |||
|
|||
test ( "_findNextFocusableTarget should find one and only one item", function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we testing an internal method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You asked:
Thanks, can you add a unit test showing the behavior? Also, this new selector is unnecessarily duplicative
To ensure that I got the extracted method to return the right thing, I wrote this unit test. I didn't want to have to do the unit-test-as-integration test where a widget is created, actions are executed and then the state of some element is assessed. That seemed less in the spirit of unit test. I'm open to suggestions though: How would you recommend exercising this?
But, let me say, this is going to go away when I reorganize the internals so let's not spend much time on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of our tests aren't unit tests. We don't really care about that level of coverage. We care about our public APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very helpful. Will comply.
}); | ||
} else { | ||
menubar._off( $anItem, "click mouseenter" ); | ||
menubar._hoverable( $anItem ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming the _off
call above can be removed, this can probably be dropped as well, since _hoverable
is already called in _initializeItems
.
Done with my review for now. I've left a bunch of comments on individual commits as well as the PR itself. I hope fixing the tabIndex=1 issue resolves a lot of the bugs we've seen before. Otherwise I think you're doing a great job at improving things. The codebase looks much better now. There are still a few odditities, as noted, but overall I can understand what's going on even though it has been years since I wrote some of the original code. |
As for the tab unit test, I lost track of what the issue is there. Maybe I can get together with @scottgonzalez later today to dig into that together. |
The reason the test fails is because you can't actually test the behavior of tab navigation. Simulating a TAB key won't actually move focus, because it's just triggering an event. We need Selenium/WebDriver in order to test this functionality, but we don't currently have a system for writing those tests. The reason this works in the dialog test suite is because the dialog plugin actually manages what happens when you press tab (assuming you're on the first or last tabbable element). You can write a test that verifies that only one menu item is tabbable at a time, and that the tabindex updates appropriately as you move focus via arrow keys, but that's about the extent of the testing that can be done at this time. |
Completed fixing several small points of Jörn: mostly whitespace or incorrect method, etc. More "substantive" changes that require a test case are underway. |
Great Scott! I will have those tests added in a jiffy. |
}); | ||
|
||
asyncTest( "Cursor keys should move focus within the menu items", function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few things here:
- Since you're not actually triggering focus, it doesn't have to be an async test anymore.
- The
debugDelay
variable can go away. - You should add an assertion that checks that the now focussed element is the only one that's tabbable. Can be one or more assertions.
Looking pretty good already. Once you fixed the tabindex to 0 (instead of 1), along with whatever other changes are still missing, I'll get back to actual testing. |
@jzaefferer I have finished implementing the issues you mentioned in various commit notes, line notes, etc. Outstanding Issues
Steps Forward
StatusFor the moment, I'm undertaking no new actions. |
I don't think those two issues are reason enough to stop. I've pinged Scott about the unwrap issue, since I don't see why it wouldn't work, and we can do the style review later, or step by step with other updates. Can you go ahead and squash commits? I'll merge then. |
This code base had been noted for being "unusual" in comparison with other widgets e.g. `dialog` by @scottgonzalez et al. Further drift was introduced by @sgharms. This commit reflects the work of bringing `menubar` closer to `dialog` by means of removing extremely unusual code invocations and by implementing feedback from a detailed review by @jzaefferer.
@jzaefferer, @scottgonzalez: We're all squashed up and ready to merge. |
Did a bit of local testing, then merged this and origin/master to bring the branch up-to-date. Great work, Steven! Of course there's still more to do. |
Cannot call methods on menu prior to initialization; attempted to call method 'collapseAll'. When using menubar don''t exist submenu.
$(function () { |
_move
was believed to specify just one item,called
focusableTarget
. Using the broaderselectors this would return anything matching
a
orbutton
. This means that the next item as wellas any
button
s ora
s found thereunder wouldalso have their focus() event fired.