JQuery 自动完成对第一个按键事件不起作用(源是一个数组)
Posted
技术标签:
【中文标题】JQuery 自动完成对第一个按键事件不起作用(源是一个数组)【英文标题】:JQuery autocomplete doesn't work on the first keypress event (the source is an array) 【发布时间】:2018-07-04 18:57:39 【问题描述】:我正在像 Google 一样创建搜索结果自动填充功能。
自动完成的结果(或源)将是一个动态数组(该数组是使用从$.ajax
调用中的URL
属性访问的对象创建的)并且每个keypress
上的元素变化非常快事件。
我的意思很简单:
-
我们有一个变量
autocompleteResults
在$.ajax
成功回调函数中,我们将此变量分配给空数组:autocompleteResults = []
在此之后,我们正在执行$.each()
函数:
$.each(d.query.pages, function(i)
autocompleteResults.push(d.query.pages[i].title);
);
// d.query.pages - JSON object from the success callback (success: function(d) ...
我们在成功回调结束时调用callback(autocompleteResults)
调用此函数有效,数组返回正确:
getAutocompleteResults(function()
console.log(autocompleteResults);
);
那么在同一个范围内:
$("#search").autocomplete(source: autocompleteResults,...);
而且它只在我第二次输入内容时起作用。
使用图片快速概览:
-
先看一下刚刚重新加载后的页面:
让我们在输入字段中输入一些内容(例如“a”):
如上图所示,我们没有自动完成结果(“a”结果只是 JS 创建的表格,与此问题无关)。让我们尝试使用键盘上的退格按钮删除“a”字符:
我们得到了与第一张图片相同的结果。但是等等,有些事情发生了变化。让我们尝试输入与第二张图片中相同的密钥,看看我们得到了什么:
奇迹!在上图中,一切都是它应该的样子。问题是只有在第二次尝试在字段中输入内容后才能获得此结果。它应该在第一次尝试时起作用。
我关于这个问题的所有研究结果:
如果不将自动完成功能放置在 keypress
事件函数中,则它可以完美运行。但是,在这种情况下,我们得到一次结果,然后它停止响应未来类型(输入“a” - 5 个结果,输入“aa” - 与“a”相同的结果并且它不响应。
我想我应该使用$( ".selector" ).autocomplete( "search", "" );
再次更改源,如here 所述,但我不确定它是否能解决这个问题。
我的代码以某种方式堆积了 AJAX 请求,并且多次重复相同的请求。我该如何解决这个问题?:
像这样的线程没有帮助: jQuery UI autocomplete with JSON, jQuery autocomplete with callback ajax json, Jquery Autocomplete Search with Ajax Request as sourcedata, https://forum.jquery.com/topic/autocomplete-with-ajax-and-json-not-working。
要查看完整的项目代码,请访问此处: https://codepen.io/Kestis500/pen/PErONL?editors=0010
或者使用代码的小sn-p(这样你就可以看到问题发生的最重要的部分):
$(function()
var autocompleteResults;
var changeText2 = function(e)
var request = $("input").val() + String.fromCharCode(e.which);
$("#instant-search").text(request);
var getAutocompleteResults = function(callback)
$.ajax(
url: "https://en.wikipedia.org/w/api.php?action=query&format=json&gsrlimit=5&generator=search&origin=*&gsrsearch=" + $('#instant-search').text(),
success: function(d)
autocompleteResults = [];
$.each(d.query.pages, function(i)
autocompleteResults.push(d.query.pages[i].title);
);
callback(autocompleteResults);
,
datatype: "json",
cache: false
);
;
getAutocompleteResults(function()
console.log(autocompleteResults);
);
$("#search").autocomplete(
source: autocompleteResults,
response: function()
if (
$("#instant-search")
.text()
)
$("table").css("display", "table");
,
close: function()
if (!$(".ui-autocomplete").is(":visible"))
$(".ui-autocomplete").show();
,
appendTo: ".input",
focus: function(e)
e.preventDefault();
,
delay: 0
);
;
var changeText1 = function(e)
if (
/[-a-z0-90áãâäàéêëèíîïìóõôöòúûüùçñ!@#$%^&*()_+|~=`\[\]:";'<>?,.\s\/]+/gi.test(
String.fromCharCode(e.which)
)
)
$("input").on("keypress", changeText2);
// THIS PART HAS NOTHING TO DO WITH THIS PROBLEM AND DELETING THIS WOULD MAKE A TABLE CREATED BY THE html TO NOT FUNCTION
var getInputSelection = function(input)
var start = 0,
end = 0;
input.focus();
if (
typeof input.selectionStart == "number" &&
typeof input.selectionEnd == "number"
)
start = input.selectionStart;
end = input.selectionEnd;
else if (document.selection && document.selection.createRange)
var range = document.selection.createRange();
if (range)
var inputRange = input.createTextRange();
var workingRange = inputRange.duplicate();
var bookmark = range.getBookmark();
inputRange.moveToBookmark(bookmark);
workingRange.setEndPoint("EndToEnd", inputRange);
end = workingRange.text.length;
workingRange.setEndPoint("EndToStart", inputRange);
start = workingRange.text.length;
return
start: start,
end: end,
length: end - start
;
;
switch (e.key)
case "Backspace":
case "Delete":
e = e || window.event;
var keyCode = e.keyCode;
var deleteKey = keyCode == 46;
var sel, deletedText, val;
val = this.value;
sel = getInputSelection(this);
if (sel.length)
// 0 kai paprastai trini po viena o 1 ar daugiau kai select su pele trini
$("#instant-search").text(
val.substr(0, sel.start) + val.substr(sel.end)
);
else
$("#instant-search").text(
val.substr(0, deleteKey ? sel.start : sel.start - 1) +
val.substr(deleteKey ? sel.end + 1 : sel.end)
);
break;
case "Enter":
if (
$("#instant-search")
.text()
.trim()
)
console.log("Redirecting...");
break;
if (!$("#instant-search")
.text()
.trim()
)
$("table, .ui-autocomplete").hide();
;
$("input").on("keydown", changeText1);
$("input").on("input", function(e)
$("#instant-search").text($("#search").val());
if (
$("#instant-search")
.text()
.trim()
)
$('table').css('display', 'table');
else
$("table").hide();
);
);
html,
body
height: 100%;
width: 100%;
body
margin: 0;
padding: 0;
font-family: sans-serif;
background-color: #000428;
/* fallback for old browsers */
background-image: -webkit-linear-gradient(to right, #004e92, #000428);
/* Chrome 10-25, Safari 5.1-6 */
background-image: linear-gradient(to right, #004e92, #000428);
/* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
.v-container
display: table;
height: 100%;
width: 100%;
.v-content
display: table-cell;
vertical-align: middle;
.text-center
text-align: center;
h1
color: #fff;
.input
overflow: hidden;
white-space: nowrap;
.input input#search
width: calc(100% - 30px);
height: 50px;
border: none;
font-size: 10pt;
float: left;
color: #4f5b66;
padding: 0 15px;
outline: none;
.input button.icon
border: none;
height: 50px;
width: 50px;
color: #4f5b66;
background-color: #fff;
border-left: 1px solid #ddd;
margin-left: -50px;
outline: none;
cursor: pointer;
display: none;
-webkit-transition: background-color .5s;
transition: background-color .5s;
.input button.icon:hover
background-color: #eee;
.ui-autocomplete
list-style: none;
background-color: #fff;
-webkit-user-select: none;
user-select: none;
padding: 0;
margin: 0;
width: 100% !important;
top: auto !important;
display: table;
table-layout: fixed;
.ui-helper-hidden-accessible
display: none;
.autocomplete-first-field
width: 15%;
display: inline-block;
.autocomplete-second-field
width: 85%;
display: inline-block;
text-align: left;
vertical-align: middle;
.three-dots
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
table
width: 100%;
border-spacing: 0;
border-collapse: collapse;
display: none;
table-layout: fixed;
table tr
background-color: #fff;
-webkit-user-select: none;
user-select: none;
tr:first-child
background-color: #ffc800;
color: #fff;
table td,
.ui-menu-item-wrapper
padding: 10px 0;
td:nth-child(2)
width: 85%;
text-align: left;
.ui-menu-item,
table
cursor: pointer;
:focus
outline: 0;
a
text-decoration: none;
color: #fff;
position: relative;
#random-article
margin-bottom: 5px;
.search-results
background: #fff;
margin-top: 50px;
border-left: 0 solid;
cursor: pointer;
-webkit-transition: border-left .5s;
transition: border-left .5s;
.search-results h4,
.search-results p
margin: 0;
padding: 10px;
.search-results:not(:first-child)
margin-top: 25px;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<div class="v-container">
<div class="v-content text-center">
<div id="random-article"><a href="https://en.wikipedia.org/wiki/Special:Random">Click here for a random WikiSearch article! :)</a></div>
<div class="input">
<input type="text" id="search" placeholder="Search...">
<button class="icon"><i class="fa fa-search"></i></button>
<table>
<tr>
<td class="fa fa-search">
<td id="instant-search" class="three-dots"></td>
</tr>
</table>
</div>
</div>
</div>
如果您对如何解决此问题有任何想法,我们将非常感谢您的帮助 :)
【问题讨论】:
【参考方案1】:您已将 source: autocompleteResults,
保留在 autocompleteResults 动态变化的位置,您应该做这样的事情
source: function (request, response)
getAutocompleteResults(function(data)
response(data);
);
,
工作代码https://codepen.io/anon/pen/OzeQvw?editors=0010
【讨论】:
以上是关于JQuery 自动完成对第一个按键事件不起作用(源是一个数组)的主要内容,如果未能解决你的问题,请参考以下文章