View
 

Selectmenu

Page history last edited by Jörn Zaefferer 1 week, 6 days ago

type: widget

release: 0.0

status:  in development

documentation: N/A

demo: http://view.jqueryui.com/selectmenu/demos/selectmenu/default.html

 

TODOs

  • Use _getCreateOptions to read disabled-attribute into options, disable/enable based on that
    • Should replace the current .attr("disabled") check
    • See Spinner for a reference (reading min/max attributes) 
  • Write unit tests to cover defaults, options, methods and events
    • Should replace most visual tests, like the event logging 
  • Check in Konquerer (see https://github.com/fnagel/jquery-ui/issues/197)
  • Implement changed ARIA specification

 


 

1 - Description:

 

A jQuery UI widget that duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select. 

 

Related plugins:

 

Previous implementations:

 

Bugfixed and jQuery 1.4.x / UI 1.8.x compatible version of this pluginPlease download repo at http://github.com/fnagel/jquery-ui/tree/selectmenu and open: demo/selectmenu/index.html
Feel free to post feature requests and bugs in the comments or even better in the GitHub issue tracker. This edit was made after consulting Todd Parker.

The wiki there has details, along with an FAQ, of what that version covers.

 

Additional Bugfixes can be found in this repo:  http://github.com/tauren/jquery-ui/tree/selectmenu. This repo is a fork of the fnagel repo listed above and includes all bug fixes and features available in that repo as well as bug fixes for positional problems such as using <optgroup> tags with scrolling popup selectmenus. A pull request has been sent for these bugfixes to be pulled into the fnagel repo. An additional demo for positional fixes has been included at https://github.com/tauren/jquery-ui/blob/selectmenu/demos/selectmenu/positioning.html. 

 


 

2 - Visual Design:

 

 


 

 

3 - Functional Specification:

 

 

The default way to use this plugin is by calling the selectmenu method on a select element:

$('select').selectmenu();

 

Feature details:

  • selectmenu will act as a proxy back to the original select element, controlling its state for form submission or serialization 
  • Any form label originally associated with the select menu will be associated with the new form control, by forwarding the click event on the original select (as long as the label's for-attribute matches the select's id-attribute).
  • The menu will support both in-place "popup" or drop-down styles
  • The menu will be fully keyboard accessible using matching conventions to native select elements
  • Menu is keyboard accessible while closed as well - arrow keys make different selections
  • The menu will have ARIA support for screenreaders so the original select element can safely be hidden from all users
  • Different arrow icons depending on menu type 
  • The presentation menu is built based on labels and values of the wrapped select. Custom presentations are possible.
  • The min-width of the menu is the width of the input. Ala autocomplete.
  • The max-height of the menu can be controlled via CSS, or, if necessary, via JS customizations  
  • For render customizations, e.g. custom background images for each item, the widget provides _renderMenu and _renderItem, like autocomplete does. Users can override these, e.g. override _renderMenu and use a template to output the markup. These need to be better documented then what's currently in place for Autocomplete.
  • A enter key event, with the input focussed, but the menu closed, does a regular form submit, just like the native select would. 
  • Type-ahead, as built-in into menu. 
  • Optgroup support just like native select does, with a flat list with group headers (similar to this categories autocomplete demo menu)
    • Optional: Render groups as nested lists, making each group a popup menu, with the top-level item the group's header 
  • Disabling individual options or optgroups happens by updating the original select, then calling the refresh method on the Selectmenu. 

 

Not supported:

  • Initializing from something that isn't a select-element. Use Menu together with Popup instead.
  • An index-method (no usecase so far). If you really need it, provide a usecase. 

 

Options: 

  • appendTo
    • see autocomplete 
  • dropdown: Boolean, default true (open below trigger, same as native select), set to false to open the menu around the trigger
  • position
    • see autocomplete 
    • might get overriden when using dropdown:false 

 

Methods:

  • refresh
    • parses the original element again, updates the value option and rerenders the menu
    • triggers events if value changed 
  • open
    • opens the menu 
  • close 
    • closes the menu 

 

Events:

  • open
    • when menu opens 
  • focus 
    • when item receives focus  
  • select  
    • when selection changes 
    • with reference to original option 
  • close
    • when menu closes 
  • change
    • on blur, when selected changed 
    • with reference to original option 

 

4 - Markup & Style:

 

     4.1 Initial markup examples

 

     <select name="speedA" id="speedA">

          <option value="Slower" class="whoo">Slower</option>

          <option value="Slow">Slow</option>

          <option value="Med" selected="selected">Med</option>

          <option value="Fast">Fast</option>

          <option value="Faster">Faster</option>

   </select>

 

     4.2 Recommended transformed HTML markup

 

          <div class="css-scope">

          <a aria-owns="speedA_menu_318" aria-haspopup="true" href="#" id="speedA_button_318" class="ui-selectmenu ui-selectmenu-popup ui-widget ui-state-default ui-corner-all" tabindex="0" style="width: 173px;">

                    <span class="ui-selectmenu-status">Slower</span>

                         <span class="ui-selectmenu-icon ui-icon ui-icon-triangle-2-n-s"></span>

           </a>

     </div>

 

     <!-- at end of body-->

     <div class="css-scope">

          <ul id="speedA_menu_318" role="menu" aria-labelledby="speedA_button_318" class="ui-selectmenu-menu ui-widget ui-widget-content ui-corner-all ui-selectmenu-menu-popup ui-selectmenu-open" style="width: 147px; left: 184.017px; top: 136.95px;">

               <li class="whoo ui-corner-top ui-selectmenu-item-selected ui-state-active"><a aria-selected="true" role="option" tabindex="-1" href="#">Slower</a></li>

               <li><a aria-selected="false" role="option" tabindex="-1" href="#">Slow</a></li>

               <li><a aria-selected="false" role="option" tabindex="-1" href="#">Med</a></li>

               <li><a aria-selected="false" role="option" tabindex="-1" href="#">Fast</a></li>

               <li class="ui-corner-bottom"><a aria-selected="false" role="option" tabindex="-1" href="#">Faster</a></li>

          </ul>

     </div>

 

     4.3 Accessibility recommendation

 

 

   Attributes on button: 

  • role="combobox" 
  • aria-haspopup="true"
  • aria-expanded (accordingly)
  • aria-autocomplete="list"
  • aria-activedescendant="[selected option's id value]" 
  • aria-owns="[widget menu's id value]"
  • generated ID for ARIA element referencing
  • tabindex of 0 or value from select element
  • aria-disabled (accordingly)
  • Keep focus on the button 

 

     ARIA attributes on menu portion:

  • role="listbox"
  • aria-labelledby="[widget button's id value]"
  • generated ID for ARIA element referencing
  • Each anchor within menu requires :
    • aria-selected (accordingly)
    • tabindex="-1"
    • role="option"

 


 

5 - Latest version of plugin:

 

http://view.jqueryui.com/selectmenu/demos/selectmenu/default.html


 

6 - Open issues being discussed

 

  • ?

 

Tabled/deferred

  • Should we have an option for scrollbarless slick scrolling (arrows at top and bottom and list scrolls dynamically with mouse position)?
    • Should be an option of menu, not selectmenu. Not planned right now.   
  • Mobile browser support: jQuery Mobile provides a good reference implementation for now, eventually we should be able to merge parts of both frameworks back together. 

Comments (Show all 65)

John said

at 5:51 pm on Dec 16, 2011

When the selectmenu is collapsed and has focus, Home/End and Page Up/Page Down should be behave the same as they do when it is expanded... right now they don't do anything.

fnagel said

at 7:56 pm on Dec 21, 2011

Ive pushed an update with some improvements and a fix for this issue. Please test and give feedback!

Thanks for reporting.

John said

at 10:33 am on Dec 22, 2011

The update fixed the issue when collapsed, but now any directional (up/down, pg up/pg down, home/end) keystroke when the menu is expanded causes the menu to collapse.

Is it desired that the list is circular when using the arrow keys? As in, when you reach the last option and press down, should it go to the first option or stay on the last option? Native browser behavior is to stay on the last option.

fnagel said

at 7:46 pm on Dec 22, 2011

Ive pushed a few commits including a fix for the above mentioned issue. Give it a try and give feedback!

John said

at 1:34 pm on Dec 23, 2011

Now we're talking! Good stuff, great job. I haven't tried pg up/pg down on a large list yet, but it looks good in the above examples.

And to the point about the arrow keys and first/last positions... the func. spec. reads, "The menu will be fully keyboard accessible using matching conventions to native select elements." If we're going for native behavior, the list shouldn't be circular. Maybe it can be an option, and it can be up for debate if it should be circular by default or not.

fnagel said

at 5:42 pm on Dec 22, 2011

Ahh, what have I done ;-) I will try to fix this asap.

Currently we do not plan to change this as Menu works that way.

George Paterson said

at 10:16 am on Jan 9, 2012

Hi, i recently worked on an alternative jQuery UI custom select widget, at the time we had performance issues with the selectmenu when a large number of custom selects were required. I rewrote the widget from the ground up to make use of the flyweight pattern.

The widget addresses a number of issues raised in the comments. It uses the select element as the primary source for the custom select value. A refresh method is called for a select element update. This is because the visible option list is a shared element, only the placeholder is generated on page load. If it can be of use for further development, i've outlined the widget below:

https://github.com/georgepaterson/jquery-ui/wiki/Selectgroup
http://www.georgepaterson.com/sandbox/jquery-ui-custom-select-demo/

fnagel said

at 1:32 pm on Jan 11, 2012

"The widget addresses a number of issues raised in the comments." Which?

So its mainly about creating the menu one time for all selects? I was not aware this is a pattern but I like the idea. Alex Farkas already asked for something similar. Copied from above "Why not delay the rendering of the menu till its clicked the first time? This could help to improve performance if many UI widget needs to be initialized."
You are using a combination of both afaics. I could imagine a11y problems when using one menu only (aria labeled-by). Any experiences with that?

George Paterson said

at 8:33 am on Jan 12, 2012

Scott's point on the select being a repository of the value not the custom element and a refresh method being available. Dave's point on some scripts may rely on the select being updated; which will happen with some .Net form implementations. The label retains a for, id link and sets focus to the placeholder. The aria-labelledby is updated to the placeholder id on selection.

As i understand it options in a select element are not read until the select is focused, this is replicated by the custom select. It has ARIA to support assistive technology and is similar to existing auto complete and dialog methods.

Scott González said

at 1:32 pm on Jan 11, 2012

I'd much rather delay rendering than have a single menu for all instances. However, even delaying the rendering can make customizations more difficult.

George Paterson said

at 8:37 am on Jan 12, 2012

We couldn't figure a useful way to progressively load unique option list for each custom select without being overly complex or resource heavy, although that doesn't preclude an alternative method. Customisation is still possible through the widget and CSS.

Jörn Zaefferer said

at 1:36 pm on Jan 11, 2012

Autocomplete creates the menu element on init, but only fills it was content when needed. That might work for selectmenu as well.

fnagel said

at 2:11 pm on Jan 25, 2012

Please note: Ive removed "lazy loading" because we need a fully created Menu widget in order to set ARIA attributes.

George Paterson said

at 8:49 am on Jan 12, 2012

The selectgroup variation is very much like the Autocomplete Combobox, the single initialisation of the option list for the selectgroup could be removed allowing each instance to have it's own option list. This could be placed at the bottom of the page or associated in the DOM with the placeholder.

fnagel said

at 2:23 pm on Jan 11, 2012

I will implement the necessary changes asap!

fnagel said

at 3:23 pm on Jan 11, 2012

Please take a look at the latest commit.

fnagel said

at 4:26 pm on Jan 12, 2012

About ARIA ToDo: "aria-activedescendent changes will, even without focus, be announced, as long as the element is visible and attached, via aria-owns, to the focussed element "
This is already done right now.

What happens when a user uses keyboard control and the menu is not opened (and therefor not visible)? Atm aria-activedescendent is set by Menu even if the menu is not visible. Is this needed?
The answer to this question is interesting because I need to know if I could remove initial menu refresh (in _move function) when using keyboard control only.

Another problem: Button anchor has role button, so screenreader user will press enter -> nothing happens. Its not obvious our button is a select so how is the user supposed to know what to do?

juan.lanus said

at 10:00 am on Jan 25, 2012

The demos in page http://jsfiddle.net/fnagel/GXtpC/embedded/result/ open the menu when right-clicked with the browser's (Chrome) context menu superimposed.
IMO should only show the browser's.

@scott: hack to link to a comment: With firebug inspect I got a comment's id and built the URL. For example this points to Felix's first comment on Selectmenu: http://wiki.jqueryui.com/w/page/12138056/Selectmenu#commentnum1318025939

juan.lanus said

at 10:14 am on Jan 25, 2012

The demos at http://jsfiddle.net/fnagel/GXtpC/embedded/result/ react only to the first letter of the item's label, as Windows did.
This design was changed so that now in Windows Explorer one can quickly type the first letters of a file name to select it, which is much better but still not best. This is not that good because it means that one has to remember part of the label and its location, 2 things instead of one.

For long lists most of the times the best behaviour is to have the list shorten to display only the elements that contain the typed text, as Autocomplete does.
In this case we should ensure that both Selectmenu and Autocomplete plugins play nicely together. I suggest to publish an integration example.
For example Autocomplete should be capable of using a Selectmenu as its data source with extreme ease.
We would end up with a nicer autocomplete, as Selectmenu seems more "designed".

fnagel said

at 2:09 pm on Jan 25, 2012

I added a comment, not sure if a notification was sent.

fnagel said

at 2:08 pm on Jan 25, 2012

@juan.lanus
This is the Wikipage for the new, built from scratch version of Selectmenu, which will hopefully be included in jQuery UI 1.9. The demo fiddles you posted use a still maintained, improved version of the selectmenu widget originally developed by Scott (filament group). Its compatible to jQuery UI and both are maintained by me. Could be confusing, Im sorry :-)
Please check and add issues at the bugtracker for the "old" version: http://github.com/fnagel/jquery-ui/issues/labels/_selectmenu


@Scott González & @Jörn Zaefferer
I would like to change the readme of the selectmenu branch in order to add some infos. This would help to avoid confusion about the branches. Ok?
Perhaps I should add a paragraph to this wiki page too.

juan.lanus said

at 2:48 pm on Jan 25, 2012

@felix:
> add issues at the bugtracker for the "old" version
I don't have issues with the "old" version, as I'm not using it.
What I want is to influence the design of the functional spec of the "next" version in order for it to be more usable.
Should I still write to the bugtracker? Else, where should I write?

fnagel said

at 4:30 pm on Jan 25, 2012

@juan
The example fiddle above (http://jsfiddle.net/fnagel/GXtpC/embedded/result/) uses the "old" version.

There is an integration example for the "new" version (this wiki page), see visual tests: http://view.jqueryui.com/selectmenu/tests/visual/selectmenu/
Both, Autocomplete and Selectmenu make use of Menu to display its list.

juan.lanus said

at 5:05 pm on Jan 25, 2012

The events test at http://view.jqueryui.com/selectmenu/tests/visual/selectmenu/events.html "wraps".
Thus:
1- select the selectmenu
2- hold down the up arrow a few seconds
It would be safer for the user if there were a "first" and a "last" item, that would serve as anchors. IMO the up key should be disabled when at the first item and the down when at the last item.
In addition to the "home" and "end" keys that work perfectly well.

An additional detail: selecting "Slow" and keying an "m" logs "Focused: Medium #2" but the selected item does not change. It does it only once. It happens again after some mouse action.

fnagel said

at 6:36 pm on Jan 26, 2012

Ive fixed the event handling so its possible again to use typeahead. Please check!

fnagel said

at 2:31 pm on Jan 26, 2012

John asked about a limitation, too. See above comments.

fnagel said

at 2:25 pm on Jan 26, 2012

Yes, thats right. Its a feature, sorta :-) Menu handles keyboard control that way we decided not to change this behaviour. I do not like it either. @Jörn & @Scott What shall we do?

Using A-Z to select an item is a probem, thanks for reporting. Will be fixed soon!

Kris Borchers said

at 2:38 pm on Jan 26, 2012

The reason menu does that is because native OS menus wrap when you reach the end and Menu was modeled after that. In my opinion, Selectmenu should stop at the top and bottom since that is the default behavior of a standard select but I would be interested in other opinions.

juan.lanus said

at 4:50 pm on Jan 25, 2012

@felix:
So, I'm checking the UI of the new Selectmenu you are building.
I find usability issues, like for example that a click in an optgroup header should not close the menu (giving the user the false feeling that she made a valid option).
Where do I report it? My purpose is to furnish you with this kind of feedback ASAP while you still are at it.
Is it right to give such feedback here?

fnagel said

at 2:29 pm on Jan 26, 2012

Yes, currently this wiki page is the best place to talk about issues. Please write a new comment on "root" for every issue.
Thanks for your contribution!

fnagel said

at 2:29 pm on Jan 26, 2012

A click in an optgroup header should not close the menu.

fnagel said

at 6:45 pm on Jan 26, 2012

Ive fixed this quick and dirty as I was not able to come up with a nicer solution.

fnagel said

at 1:06 pm on Jan 27, 2012

I would like to implement lazy loading (call refresh method when button gets focus) again but Im not sure if we need to set the ARIA attributes on init in order to make it accessible.
Any suggestions?

Jörn Zaefferer said

at 3:03 pm on Jan 27, 2012

Which attributes does this affect?

Is the menu creation part of the lazy load? Or just the menu items?

fnagel said

at 4:52 pm on Jan 27, 2012

aria-activedescendant and aria-selected

Just the menu items as autocomplete does.

fnagel said

at 1:10 pm on Jan 27, 2012

What about removing the Button widget dependency?
Button has about 400 lines but we would need about 10 lines more to achieve similar functionality.

fnagel said

at 4:49 pm on Jan 27, 2012

I would like to remove it for now as its a unneeded dependency atm.

Scott González said

at 3:16 pm on Jan 27, 2012

It seems strange to me that selectmenu would use button at all.

Jörn Zaefferer said

at 3:02 pm on Jan 27, 2012

There's a Button rewrite planned. It might get some inspiration from jQuery Mobile's buttonMarkup component, which could make it a lot more useful for Selectmenu.

fnagel said

at 4:49 pm on Jan 27, 2012

Ive improved the handling of empty select and empty option tags but its pretty hard to handle empty optgroups. Any ideas?

You don't have permission to comment on this page.