title: Tab Navigation not working for Autocomplete text box on Mozilla Firefox
body: <p>I am using 'jquery.ui.autocomplete.js'. What issue I am facing is that during TAB Press default Naviagtion get stuck
  when it reached in Autocomplete Text Box. The issue is reflecting only in Mozilla Firefox. What I want is that on TAB key press
  it shold move to next elemnt. Can anyone please assist me to fix this issue?</p>
  
  <p>I have tried Googled solutions but not able to fix. I am posting some link hope it will help you to understand isue.
  1. <a href="http://bugs.jqueryui.com/ticket/6661" rel="nofollow">http://bugs.jqueryui.com/ticket/6661</a></p>
  
  <p>I think issue is somewhere in these lines:</p>
  
  <pre><code>        case keyCode.ENTER:
          case keyCode.NUMPAD_ENTER:
              // when menu is open or has focus
              if (self.menu.element.is(":visible")) {
                  event.preventDefault();
              }
              //passthrough - ENTER and TAB both select the current element
          case keyCode.TAB:
              if (!self.menu.active) {
                  return;
              }
              self.menu.select(event);
              break;
          case keyCode.ESCAPE:
              self.element.val(self.term);
              self.close(event);
              break;
          default:
              // keypress is triggered before the input value is changed
              clearTimeout(self.searching);
              self.searching = setTimeout(function () {
                  // only search if the value has changed
                  if (self.term != self.element.val()) {
                      self.selectedItem = null;
                      self.search(null, event);
                  }
              }, self.options.delay);
              break;
      }
  })
  </code></pre>
  
  <p>My jquery code is here:</p>
  
  <pre><code>(function ($, undefined) {
  
      $.widget("ui.autocomplete", {
          options: {
              appendTo: "body",
              delay: 300,
              minLength: 1,
              position: {
                  my: "left top",
                  at: "left bottom",
                  collision: "none"
              },
              source: null
          },
          _create: function () {
              var self = this,
              doc = this.element[0].ownerDocument;
              this.element
              .addClass("ui-autocomplete-input")
              .attr("autocomplete", "off")
              // TODO verify these actually work as intended
              .attr({
                  role: "textbox",
                  "aria-autocomplete": "list",
                  "aria-haspopup": "true"
              })
              .bind("keydown.autocomplete", function (event) {
                  if (self.options.disabled || self.element.attr("readonly")) {
                      return;
                  }
  
                  var keyCode = $.ui.keyCode;
                  switch (event.keyCode) {
                      case keyCode.PAGE_UP:
                          self._move("previousPage", event);
                          break;
                      case keyCode.PAGE_DOWN:
                          self._move("nextPage", event);
                          break;
                      case keyCode.UP:
                          self._move("previous", event);
                          // prevent moving cursor to beginning of text field in some browsers
                          event.preventDefault();
                          break;
                      case keyCode.DOWN:
                          self._move("next", event);
                          // prevent moving cursor to end of text field in some browsers
                          event.preventDefault();
                          break;
                      case keyCode.ENTER:
                      case keyCode.NUMPAD_ENTER:
                          // when menu is open or has focus
                          if (self.menu.element.is(":visible")) {
                              event.preventDefault();
                          }
                          //passthrough - ENTER and TAB both select the current element
                      case keyCode.TAB:
                          if (!self.menu.active) {
                              return;
                          }
                          self.menu.select(event);
                          break;
                      case keyCode.ESCAPE:
                          self.element.val(self.term);
                          self.close(event);
                          break;
                      default:
                          // keypress is triggered before the input value is changed
                          clearTimeout(self.searching);
                          self.searching = setTimeout(function () {
                              // only search if the value has changed
                              if (self.term != self.element.val()) {
                                  self.selectedItem = null;
                                  self.search(null, event);
                              }
                          }, self.options.delay);
                          break;
                  }
              })
  
              .bind("focus.autocomplete", function () {
                  if (self.options.disabled) {
                      return;
                  }
  
                  self.selectedItem = null;
                  self.previous = self.element.val();
              })
          .bind("blur.autocomplete", function (event) {
              if (self.options.disabled) {
                  return;
              }
  
              clearTimeout(self.searching);
              // clicks on the menu (or a button to trigger a search) will cause a blur event
              self.closing = setTimeout(function () {
                  self.close(event);
                  self._change(event);
              }, 150);
          });
              this._initSource();
              this.response = function () {
                  return self._response.apply(self, arguments);
              };
              this.menu = $("&lt;ul&gt;&lt;/ul&gt;")
              .addClass("ui-autocomplete")
              .appendTo($(this.options.appendTo || "body", doc)[0])
              // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
              .mousedown(function (event) {
                  // clicking on the scrollbar causes focus to shift to the body
                  // but we can't detect a mouseup or a click immediately afterward
                  // so we have to track the next mousedown and close the menu if
                  // the user clicks somewhere outside of the autocomplete
                  var menuElement = self.menu.element[0];
                  if (event.target === menuElement) {
                      setTimeout(function () {
                          $(document).one('mousedown', function (event) {
                              if (event.target !== self.element[0] &amp;&amp;
                                  event.target !== menuElement &amp;&amp;
                                  !$.ui.contains(menuElement, event.target)) {
                                  self.close();
                              }
                          });
                      }, 1);
                  }
  
                  // use another timeout to make sure the blur-event-handler on the input was already triggered
                  setTimeout(function () {
                      clearTimeout(self.closing);
                  }, 13);
              })
              .menu({
                  focus: function (event, ui) {
                      var item = ui.item.data("item.autocomplete");
                      if (false !== self._trigger("focus", null, { item: item })) {
                          // use value to match what will end up in the input, if it was a key event
                          if (/^key/.test(event.originalEvent.type)) {
                              self.element.val(item.value);
                          }
                      }
                  },
                  selected: function (event, ui) {
                      var item = ui.item.data("item.autocomplete"),
                          previous = self.previous;
  
                      // only trigger when focus was lost (click on menu)
                      if (self.element[0] !== doc.activeElement) {
                          self.element.focus();
                          self.previous = previous;
                      }
  
                      if (false !== self._trigger("select", event, { item: item })) {
                          self.element.val(item.value);
                      }
  
                      self.close(event);
                      self.selectedItem = item;
                  },
                  blur: function (event, ui) {
                      // don't set the value of the text field if it's already correct
                      // this prevents moving the cursor unnecessarily
                      if (self.menu.element.is(":visible") &amp;&amp;
                          (self.element.val() !== self.term)) {
                          self.element.val(self.term);
                      }
                  }
              })
              .zIndex(this.element.zIndex() + 1)
              // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
              .css({ top: 0, left: 0 })
              .hide()
              .data("menu");
              if ($.fn.bgiframe) {
                  this.menu.element.bgiframe();
              }
          },
  
          destroy: function () {
              this.element
              .removeClass("ui-autocomplete-input")
              .removeAttr("autocomplete")
              .removeAttr("role")
              .removeAttr("aria-autocomplete")
              .removeAttr("aria-haspopup");
              this.menu.element.remove();
              $.Widget.prototype.destroy.call(this);
          },
  
          _setOption: function (key, value) {
              $.Widget.prototype._setOption.apply(this, arguments);
              if (key === "source") {
                  this._initSource();
              }
              if (key === "appendTo") {
                  this.menu.element.appendTo($(value || "body", this.element[0].ownerDocument)[0])
              }
          },
  
          _initSource: function () {
              var array,
              url;
              if ($.isArray(this.options.source)) {
                  array = this.options.source;
                  this.source = function (request, response) {
                      response($.ui.autocomplete.filter(array, request.term));
                  };
              } else if (typeof this.options.source === "string") {
                  url = this.options.source;
                  this.source = function (request, response) {
                      $.getJSON(url, request, response);
                  };
              } else {
                  this.source = this.options.source;
              }
          },
  
          search: function (value, event) {
              value = value != null ? value : this.element.val();
              if (value.length &lt; this.options.minLength) {
                  return this.close(event);
              }
  
              clearTimeout(this.closing);
              if (this._trigger("search") === false) {
                  return;
              }
  
              return this._search(value);
          },
  
          _search: function (value) {
              this.term = this.element
              .addClass("ui-autocomplete-loading")
              // always save the actual value, not the one passed as an argument
              .val();
  
              this.source({ term: value }, this.response);
          },
  
          _response: function (content) {
              if (content.length) {
                  content = this._normalize(content);
                  this._suggest(content);
                  this._trigger("open");
              } else {
                  this.close();
              }
              this.element.removeClass("ui-autocomplete-loading");
          },
  
          close: function (event) {
              clearTimeout(this.closing);
              if (this.menu.element.is(":visible")) {
                  this._trigger("close", event);
                  this.menu.element.hide();
                  this.menu.deactivate();
              }
          },
  
          _change: function (event) {
              if (this.previous !== this.element.val()) {
                  this._trigger("change", event, { item: this.selectedItem });
              }
          },
  
          _normalize: function (items) {
              // assume all items have the right format when the first item is complete
              if (items.length &amp;&amp; items[0].label &amp;&amp; items[0].value) {
                  return items;
              }
              return $.map(items, function (item) {
                  if (typeof item === "string") {
                      return {
                          label: item,
                          value: item
                      };
                  }
                  return $.extend({
                      label: item.label || item.value,
                      value: item.value || item.label
                  }, item);
              });
          },
  
          _suggest: function (items) {
              var ul = this.menu.element
                  .empty()
                  .zIndex(this.element.zIndex() + 1),
              menuWidth,
              textWidth;
              this._renderMenu(ul, items);
              // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
              this.menu.deactivate();
              this.menu.refresh();
              this.menu.element.show().position($.extend({
                  of: this.element
              }, this.options.position));
  
              menuWidth = ul.width("").outerWidth();
              textWidth = this.element.outerWidth();
              ul.outerWidth(Math.max(menuWidth, textWidth));
          },
  
          _renderMenu: function (ul, items) {
              var self = this;
              $.each(items, function (index, item) {
                  self._renderItem(ul, item);
              });
          },
  
          _renderItem: function (ul, item) {
              return $("&lt;li&gt;&lt;/li&gt;")
              .data("item.autocomplete", item)
              .append($("&lt;a&gt;&lt;/a&gt;").text(item.label))
              .appendTo(ul);
          },
  
          _move: function (direction, event) {
              if (!this.menu.element.is(":visible")) {
                  this.search(null, event);
                  return;
              }
              if (this.menu.first() &amp;&amp; /^previous/.test(direction) ||
                  this.menu.last() &amp;&amp; /^next/.test(direction)) {
                  this.element.val(this.term);
                  this.menu.deactivate();
                  return;
              }
              this.menu[direction](event);
          },
  
          widget: function () {
              return this.menu.element;
          }
      });
  
      $.extend($.ui.autocomplete, {
          escapeRegex: function (value) {
              return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&amp;");
          },
          filter: function (array, term) {
              var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");
              return $.grep(array, function (value) {
                  return matcher.test(value.label || value.value || value);
              });
          }
      });
  
  } (jQuery));
  </code></pre>