Skip to content

Selectmenu: Prevent exception when the user types in selectmenu, when the result is an optgroup #1329

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

Closed
wants to merge 1 commit into from
Closed

Selectmenu: Prevent exception when the user types in selectmenu, when the result is an optgroup #1329

wants to merge 1 commit into from

Conversation

SimenB
Copy link
Contributor

@SimenB SimenB commented Aug 29, 2014

Hi!

This PR is probably done somewhat wrong, but I thought I should get this in before the weekend.

Ticket: http://bugs.jqueryui.com/ticket/10571

If you have a Selectmenu with optgroups, and type while it has focus, it may hit an optgroup as a result. If this happens, you get an exception.

Fiddle: http://jsfiddle.net/coLcs5pz/1/

Just put focus on the selectmenu, and type S, and you'll get an exception in the console.
Uncaught TypeError: Cannot read property 'index' of undefined

There is probably some better way to solve this problem, but this fixes it for us at least.

@SimenB
Copy link
Contributor Author

SimenB commented Aug 29, 2014

Build failure... The proxy at work prevents me from actually cloning from GitHub, but if you haven't done anything with this until tomorrow (CET), I'll take a look at it.

EDIT: Only JSHint error. I'll squash commits tomorrow (I'm doing these commits through GH's website).

I can add a test as well

@scottgonzalez
Copy link
Member

Thanks, please start by filing a bug report. We'll also need you to sign our CLA. You should read through the contributing guidelines as it documents how to properly contribute.

@SimenB
Copy link
Contributor Author

SimenB commented Aug 29, 2014

Filed CLA and bug

Anything else I'm missing? Other than the fact I should probably write a unit test for this.

@scottgonzalez
Copy link
Member

That's it. Though now that I'm looking at your code, I don't think this is the right fix. The underlying problem is that optgroups shouldn't be able to get focus in the first place.

@SimenB
Copy link
Contributor Author

SimenB commented Aug 29, 2014

So I should look in menu.js instead, and do some filtering? I've only really started looking at the internals of jQuery UI after you went AMD, so I'm not familiar at all with the codebase

@scottgonzalez
Copy link
Member

Yeah, menu's key handling should ignore dividers.

@SimenB
Copy link
Contributor Author

SimenB commented Aug 29, 2014

Ping @scottgonzalez I tried changing code in menu now, is that closer to a good solution?

I messed up when trying to clean up formatting (editing files and keeping the styling when copying from IDEA into GH's editor isn't easy!). I'll squash away the commits tomorrow

@@ -243,7 +243,7 @@ return $.widget( "ui.menu", {

regex = new RegExp( "^" + escape( character ), "i" );
match = this.activeMenu.find( this.options.items ).filter(function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't you just change this line to use ".ui-menu-item" instead of this.options.items?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm...that change alone probably isn't good, since it will traverse into submenus. I don't think we've spent any time thinking about how this should behave with submenus.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably the easiest solution to this while ignoring the submenu question is to just add another filter:

match = this.activeMenu
    .find( this.options.items )

    // Only match on items, not dividers or other content (#10571)
    .filter( ".ui-menu-item" )
    .filter(function() {
        ...

@SimenB
Copy link
Contributor Author

SimenB commented Aug 30, 2014

Ping @scottgonzalez OK, I've added your solution now, and wrote a test for it.

The test is in selectmenu_events, while it should probably be in menu_events, but I couldn't figure out how to properly test it there. And I suppose a test for exactly what triggered the error isn't wrong anyway.
Any ideas on adding a test to menu_events as well?

@SimenB
Copy link
Contributor Author

SimenB commented Sep 1, 2014

The same search is performed right under if there's no match.
https://github.com/jquery/jquery-ui/pull/1329/files#diff-d338fe82d253858f3e1ce2f17e82f104R261

Should the menu-item filter be applied there as well?

Another question: would it make sense to cache the menu-items like this.options.items (this.options.menutimes?) is now, to avoid having to filter through everything every time? IDK, just throwing out ideas.

@scottgonzalez
Copy link
Member

We should probably pull the logic out into a method and call it in both locations to avoid the duplication. Caching the items would require tracking them on a per menu basis (note that this isn't a per instance basis because menus nest automatically).

@scottgonzalez
Copy link
Member

What was making it tricky to test this directly on menu? Isn't it pretty much the exact same test?

@SimenB
Copy link
Contributor Author

SimenB commented Sep 5, 2014

I moved the initial filtering (excluding the regex-check) into it's own variable, does that work?

My problem writing a test in menu_events is that in a normal menu, I can't seem to figure out what is not considered a menu-item. Both class="ui-state-disabled" and class="ui-menu-group" items get the ui-menu-item-class, so I suppose they're not supposed to get filtered out.

@scottgonzalez
Copy link
Member

I moved the initial filtering (excluding the regex-check) into it's own variable, does that work?

The logic is still exactly the same, why not just move everything into a function and pass the regex?

My problem writing a test in menu_events is that in a normal menu, I can't seem to figure out what is not considered a menu-item.

Anything that doesn't match the items option.

@SimenB
Copy link
Contributor Author

SimenB commented Sep 5, 2014

Something like how it is now?

Anything that doesn't match the items option.

But that matches all the children of the menu, right ("> *")? I worked around it by making it a divider, but it seems kind of hackish.

Should I remove the test from Selectmenu? I feel like the test in there is more of a real use-case which kind of justifies it's existence.

Thank you for your patience with me, btw. I bet you could have fixed it yourself quicker, and with less effort, than this.

@SimenB SimenB changed the title Selectmenu: Prevent exception when the user types in selectmenu, when teh result is an optgroup Selectmenu: Prevent exception when the user types in selectmenu, when the result is an optgroup Sep 6, 2014
@SimenB
Copy link
Contributor Author

SimenB commented Sep 15, 2014

Ping @scottgonzalez Is there anything else I can do with this?

@scottgonzalez
Copy link
Member

Sorry for the delay, I was traveling last week. I'll likely get back to this tomorrow.

element.menu({
focus: function( event, ui ) {
equal( ui.item.length, 1, "There should only be one match when filtering" );
ok( ui.item.hasClass( "ui-menu-item" ), "element is .ui-menu-item" );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should verify that the correct element is provided, not just that it's a menu item.

@scottgonzalez
Copy link
Member

We're very close to being able to land this :-) Let me know if you need any help with the test update.

@SimenB
Copy link
Contributor Author

SimenB commented Sep 18, 2014

Ok, that last push should cover your comments.

@scottgonzalez
Copy link
Member

Thanks. Just landed this in master :-)

@SimenB SimenB deleted the selectmenu-exception-optgroup branch October 18, 2014 17:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants