AJAX 揭秘 - 第四部分 - AJAX 自动建议文本框






4.64/5 (10投票s)
创建一个无需数据库或服务器端脚本的 AJAX 自动建议文本框或文本区域。
引言
我有一部摩托罗拉 Razr 手机,有一天我在发送短信,它令人印象深刻的“自动建议”功能给我留下了深刻的印象。对于不知道我说的是什么的,当你打字时,手机会建议你在文本后面的单词。要插入单词,只需向上按键盘即可。这使得发送短信更加容易,同时也确保了拼写正确。因此,考虑到这一点,我着手为 Web 表单做同样的事情。当然,我见过很多带有自动建议的 WinForms 应用程序,我知道那里有一些控件集包含自动建议下拉列表和文本框(Anthem.NET Extensions 有一个似乎运行良好,但你必须将其绑定到数据库进行单词查找)。我想要一些配置很少,不需要数据库,但仍然可以自定义的东西。
引入 XMLHTTPRequest
对象。我写了几篇关于在 AJAX 应用程序中使用它的文章,并认为它在这里会很有用。结果是一个 ASP.NET (2.0) Web 用户控件,其中包含一个文本框和一个 div
元素,该元素会在你输入文本时显示建议(见截图)。
Using the Code
我将介绍将此集成到你的项目中的步骤。这真的非常简单,我将在最后添加一个最终的检查清单,以防你遇到任何问题。
设置项目
我已经包含了运行此程序所需的所有代码和一个示例词典。单词列表远非完整,所以你可能想删除其中的许多内容,但这毕竟只是一个例子。单词列表的格式是a.txt、b.txt 等。每个文本文件包含以 a-z 中的一个字符开头的单词。我这样做的原因是为了将 XMLHTTPRequest
的大小降至最低。当你在文本框中键入“D”时,请求只会加载 d.txt 文件,因此,所有以字母 d 开头的单词。你需要确保 dictionary 目录存在于你打算使用此控件的任何位置的根目录中,因为 JavaScript 会查找 dictionary/a.txt。你可以轻松打开和修改这些文本文件,因为它们只是逗号分隔的。请记住,单词越多,查找速度就越慢,因为它必须加载整个库来搜索和匹配单词。
你需要确保目录(dictionary)和所有文件都可以读取,否则你会收到一个权限被拒绝的 JavaScript 错误。
还包含一个 img 目录。确保它也在你的根目录中,或者,如果你有不同的文件夹,只需修改 img
元素以指向你决定放置它们的任何位置。只有两个图像(up.png 和 loading.gif)。
使用控件
所有文件都就位后,只需将用户控件添加到你的 Web 项目中。你可以简单地将控件拖放到页面上。如果你想编辑大小等,只需修改控件代码隐藏的 HTML 中的 CSS。我没有包含任何属性,因为如前所述,我希望它能够在没有任何服务器端脚本的情况下运行。
你会在页面上看到该控件,它应该像上面的截图一样进行样式设置。就是这样!
工作原理
我们使用 TextBox
输入的“onkeyup
”事件来开始这个过程。一旦按下按键,我们就进行一些检查。首先,我们要查看用户是否关闭了自动建议(通过取消选中复选框)。接下来,我们获取键码。如果它是“向上箭头”(代码 38),我们将尝试将当前单词插入文本框,只要我们有单词。由于我们将单词嵌套在一个锚定标签中(我希望用户能够单击超链接以及按下向上箭头来插入),我们将获取该对象的 innerText
属性。
如果我们正在获取一个新单词,我们将使用 JavaScript 的 setTimeout
方法设置一个计时器。这样做是为了在 250 毫秒后异步触发 checkSuggest
方法。我之所以这样做,是因为如果没有异步调用,XMLHTTPRequest
的加载实际上会阻止用户在 XMLHTTPRequest
加载之前将文本输入到文本框中,这对我来说是不可接受的。checkSuggest
方法只是确保我们输入的是一个“有效”字符(a-z),而不是空格、数字或标点符号。
function BeginSearch()
{
if (!UseAutosuggest())
return;
// If up arrow is pressed, insert the word
var keyID = event.keyCode;
if (keyID == 38) // Up arrow
{
var suggest = document.getElementById('suggest');
if (suggest.innerText == "No suggestions.")
return;
var link = document.getElementById('lnkWord');
var elem = document.getElementById('txtInput');
setText(link.innerText);
return;
}
Working(true); //Show the working graphic
// Use a timeout to help with input keying
var timerId = setTimeout(checkSuggest,250);
}
一旦我们确定有一个有效字符,XMLHTTPRequest
就会负责加载单词库,并返回一个与当前键入单词的第一个字母和长度相匹配的单词数组。JavaScript 处理所有其余的匹配和显示,所以真的不需要服务器端代码。你可以直接从控件中复制 HTML、CSS 和 JavaScript,并在任何 HTML 页面上独立使用它。配置服务器端只需要对单词列表的读取访问。suggestWord
函数接受 checkText
参数。我们将获取第一个字符,并加载相应的库。
// Load the library of words
var dict = "dictionary/" + checkText.charAt(0) + ".txt";
xmlhttp.open("GET",dict,true);
asynchText = checkText;
xmlhttp.onreadystatechange = MatchWords;
xmlhttp.send(null);
MatchWords
回调函数处理响应并解析结果文本,删除任何比我们输入的单词短的单词(如果我输入“and”,我就不应该获得“an”的建议),然后检查每个单词是否与我们返回的数组中的单词匹配。所以,如果我输入“app”,我应该得到“apple”(只要它在单词列表中,如果你使用我的,你会得到“Appalachia”)。
// Rule out all words that are less than the length of the text
var newSuggest = "";
var arLen=temp.length;
for ( var i=0, len=arLen; i<len; /> checkText.length)
{
newSuggest += temp[i] + ",";
}
}
现在我们有了单词列表(在一个数组中),我们将对它们进行排序,然后开始将它们与我们输入的文本进行比较。我们只是通过循环遍历单词的每个字符来实现这一目标,直到出现不匹配。如果匹配失败,我们就继续处理列表中的下一个单词。如果我们到达输入单词的末尾,并且仍然全部匹配,那么这一定是正确的单词。
function checkMatch(inputText, dictWord)
{
inputText = inputText.toUpperCase();
dictWord = dictWord.toUpperCase();
for (var x=0; x<inputText.length; x++)
{
if (inputText.charAt(x) != dictWord.charAt(x))
return false;
}
return true;
}
其余的 JavaScript 处理所有必需字段的样式设置和更新。如果你只是打算在你的网站中使用此控件,这可能对你来说不会非常重要。只需记住,单词列表越小,自动建议的速度就越快。
另外值得注意的是,此控件可以处理多词输入,因此你可以轻松地将其扩展到具有相同功能的文本区域输入。
安装清单
- 启动一个新的 ASP.NET 网站(2.0)
- 解压 AutoSuggest 源代码
- 将用户控件添加到你的网站项目中
- 在控件所在位置的根目录下添加名为“dictionary”和“img”的目录
- 将解压后的源代码的 dictionary 文件夹中的所有文件添加到你的 dictionary 文件夹(你可以在解决方案资源管理器中添加文件)
- 将 up.png 和 loading.gif 添加到你的 img 文件夹
- 将控件拖到你的页面上
- 构建并执行
发布版本中还包含独立的 HTML、CSS 和 JavaScript 文件,用于在没有网站项目的情况下进行测试。它们可以在 Zip 文件的 /html 目录中找到。你需要将它们移动到与 dictionary 和 image 文件夹相同的根目录下。
可能的升级
我是一名 C# 程序员,只涉足 JavaScript 编程,所以我确信 JavaScript 中存在许多低效之处。请随时修改 JavaScript 并在此处发布一些可能的改进。只要是建设性的,我很乐意对源代码进行更改。我这样做是为了好玩,并展示 XMLHTTPReuest
对象在 UI 编程中的一些其他可能用途。
最终,我也希望将建议变成一个可滚动列表。所以,如果我输入“app”,我可能会得到几个建议,例如“apple”、“apply”等。目前,此控件一次只能显示一个建议。
同样重要的是要认识到,本文中发布的代码由代码片段组成。完整源代码包含在下载文件中,因此诸如实例化 XMLHTTPRequest
之类的内容已从本文中省略。
祝你 XMLHTTPRequest 愉快!