Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#9463 closed bug (notabug)

Autocomplete keyboard navigation

Reported by: jdmx Owned by:
Priority: minor Milestone: none
Component: ui.autocomplete Version: 1.10.3
Keywords: Cc:
Blocked by: Blocking:

Description

I have setup the autocomplete to use a label/value pair for showing data. Everything works except for when I keyboard navigate ( using the up and down arrows ) through the menu. Then the value is show and not the label value.

You can see the problem with the Remote JSONP datasource datasource example http://jqueryui.com/autocomplete/#remote-jsonp . The label displayed in the menu dropdown will not match the value in the textbox when using the keyboard up/down buttons to do the select.

I have narrowed the problem to this section of the autocomplete that handles the keyboard movements through the menu.

                                var item = ui.item.data( "ui-autocomplete-item" );
                                if ( false !== this._trigger( "focus", event, { item: item } ) ) {
                                        // use value to match what will end up in the input, if it was a key event
                                        if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
                                                this._value( item.value );
                                        }
                                } else {
                                        // Normally the input is populated with the item's value as the
                                        // menu is navigated, causing screen readers to notice a change and
                                        // announce the item. Since the focus event was canceled, this doesn't
                                        // happen, so we update the live region so that screen readers can
                                        // still notice the change and announce it.
                                        this.liveRegion.text( item.value );
                                }

if I change the code by adding the line

 var s = item.label || item.value;

and then updating the sets, then menu navigation works correctly.

                                var item = ui.item.data( "ui-autocomplete-item" );
                                var s = item.label || item.value;
                                if ( false !== this._trigger( "focus", event, { item: item } ) ) {
                                        // use value to match what will end up in the input, if it was a key event
                                        if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
                                                this._value( s );
                                        }
                                } else {
                                        // Normally the input is populated with the item's value as the
                                        // menu is navigated, causing screen readers to notice a change and
                                        // announce the item. Since the focus event was canceled, this doesn't
                                        // happen, so we update the live region so that screen readers can
                                        // still notice the change and announce it.
                                        this.liveRegion.text( s );
                                }

I guess the ultimate solution would be to tie the navigation to the onchange event ( or a new event ) so that the user has the ability to change the "value" being displayed in the textbox when the next item in the list is keyboard navigated to.

I found the focus example that handles the textbox change on the navigation

    focus: function( event, ui ) {
      $( "#project" ).val( ui.item.label );
      return false;
    },

but that seems far more cumbersome than it needs to be to get the label to show in the textbox.

Change History (5)

comment:1 Changed 7 years ago by Scott González

Resolution: notabug
Status: newclosed

This behavior is by design and is pretty clearly documented: http://api.jqueryui.com/autocomplete/#option-source

comment:2 Changed 7 years ago by jdmx

Not sure if you continue to moniter closed tickets but..

If I use the focus trick

  focus: function( event, ui ) {
    $( "#project" ).val( ui.item.label );
    return false;
  },

to set the the textbox value to the item label and have autoFocus: true, then I am no longer able to use the backspace key in the textbox because the keypress will redo the list, causing the first item to be focused, reseting the textbox value.

comment:3 Changed 7 years ago by Scott González

You either want the label in the text field or you want the value. You can't have both.

comment:4 Changed 7 years ago by jdmx

I have not stated what I am doing clearly enough.

My use of the autocomplete is a compliation of a number of the demos listed on the site.

I am using a remote datasource to pull in the values to display and setting them to a json value/label list where the value is a number and the label is a string. The getting of the list is done by searching on the label value.

$.getJSON(this.url, qs, function (data, status, xhr) {
  var o = data[0];
  var s = '[';
  var i = 0;
  for (var key in o) {
    s += (i == 0 ? '' : ', ') + '{ "value": "' + key + '", "label": "' + o[key] + '" }';
    i++;
  }
  s += ']';
  s = $.parseJSON(s);
  c._setCache(ele, term, s);
  response(s);
});

Everything thing works the way I expect to... enter a value in the textbox and as the value is being typed in, the menu is populated with a decreasing number of selections. If the mouse selects an item, the value of the text box is set by me when I override the select method

      select: function (event, ui) {
        var _id = this.name.substring(0, this.name.length - 2);
        if (document.getElementById(_id))
          document.getElementById(_id).value = ui.item.value;
        document.getElementById(this.name).value = ui.item.label;
        this.value = ui.item.label;
        return false;
      }

I want the autoFocus to be set to true so that when the user tabs out of the field, the first item is selected automactically. Without it, the user is forced to make a selection from the list before continuing.

But if the user uses the arrows keys to nav down the list, instead of showing the labels, it will show the values ( the numbers ). If they make a selection, then it will go back to the label.

Now to fix the numbers showing up instead of the labels, I use the focus trick to get the textbox to show right. But when autoFocus is true and focus is set to the function that resets the textbox value, I end up autoselecting the first item of the returned list and making the backspace button unusable.

So at this point, I am left with 1 of 2 options, either keep the autofocus: true but have the arrow buttons display the numbers when used OR override the focus function with autofocus: false and have to worry about a user tabbing out of the text box without physically making a selection.

To see the what I mean by tabbing, using the example http://jqueryui.com/autocomplete/#custom-data, type in jq and then tab out of the field. The select function is not called so it does not change the icon and subtext.

In the src bit I provided, it allows me to control the value being displayed in the textbox while still having the autoFocus: true. I know that the bit breaks functionality that has been documented, but instead of using the line

var s = item.label || item.value;

it would call an event that would allow for the user to provide an override, like how the focus and select overrides work, then there would not be an issue of the focus and autoFocus conflicting like I discussed above

I guess my final option is to just switch the value/label assignments so that the value is the string and the label is the number so that I can circumvent this quirk.

comment:5 Changed 7 years ago by Scott González

Tell the plugin not to update the value on focus, via event.preventDefault(). Set the value on select. If you need more help, please use the forums, IRC, or Stack Overflow.

Note: See TracTickets for help on using tickets.