我正在使用' jquery.ui.autocomplete.js'。我面临的问题是,在TAB Press期间,默认Naviagtion卡住了 当它到达自动填充文本框时。该问题仅反映在Mozilla Firefox中。我想要的是在TAB按键上 它将移动到下一个元素。有人可以帮我解决这个问题吗?
我尝试过Googled解决方案,但无法修复。我发布一些链接希望它能帮助你理解isue。 1. http://bugs.jqueryui.com/ticket/6661
我认为问题出在以下几个方面:
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;
}
})
我的jquery代码在这里:
(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 = $("<ul></ul>")
.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] &&
event.target !== menuElement &&
!$.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") &&
(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 < 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 && items[0].label && 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 $("<li></li>")
.data("item.autocomplete", item)
.append($("<a></a>").text(item.label))
.appendTo(ul);
},
_move: function (direction, event) {
if (!this.menu.element.is(":visible")) {
this.search(null, event);
return;
}
if (this.menu.first() && /^previous/.test(direction) ||
this.menu.last() && /^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, "\\$&");
},
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));
答案 0 :(得分:0)
是的,您链接到的错误提示会显示您need to follow的变更集。
请注意,而不是说$('selector').autocomplete(...)
您应该这样做:
$('selector').bind('keydown', function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).data('autocomplete').menu.active ) {
event.preventDefault();
}
}).autocomplete(...)
请注意,如果菜单处于“活动状态”,您正在拦截TAB键盘,并阻止事件执行默认行为,而在浏览器中,该行为正在关注下一个静态布局的元素。