一个网站的诞生- MagicDict开发总结5 [检索候补列表的生成]
一边输入检索词语的同时,一边能够在网页的下拉列表中显示候补词语,作为一个日语单词检索网站,这个是必须的。
至于使用什么技术,Ajax以外似乎没有其他选择了。以前是手工写Ajax的代码的,现在有Jquery了,我也随大流了,用JQuery写Ajax。。。function GetSug(ReadyToSearch) {
if (ReadyToSearch == searchKey) {
$.get("ASHX/GetWordList.ashx",
{ SearchKey: searchKey },
function(data) {
if (!(data.toString()=="" | data.toString()== "[object XMLDocument]")) {
//列表框表示
document.getElementById("jp_wordlist").innerHTML = data;
document.getElementById("jp_wordlist").style.display = "block";
_wListInited = true;
} else {
document.getElementById("jp_wordlist").style.display = "none";
_wListInited = false;
}
}
);
}
}
这段代码非常简单,其核心就是一个Jquery的$.get传入现在用户已经输入完成的词语。然后交给后台去检索出可以使用的候补词语(其结果是一个HTML的TABLE),如果有结果的话,将结果表示出来。
原理就这么简单了,但是,3个问题是必须要注意的
1.检索效率问题。
用户在不停的输入内容,是不是客户端输入任何东西都要第一时间去访问服务器端,获取候补词语呢? 当然不是咯,首先,你的服务器承受不了这样的检索操作,一般用户的打字速度,1秒里面打4,5个字母是完全没有问题的,单用户1秒钟做4-5次检索,这个不是一件有趣的事情。再者,没有必要,候补列表只是辅助作用的,一般在用户记忆比较模糊的时候,才会从列表里面来选择检索关键字。
综上所述,我的策略是,当用户没有任何输入动作2-3秒后,才去做Ajax的检索操作。【其实,一般考虑都是这样的】
2.列表中关键字的选取方法。
列表中关键字的选取方法,牵涉到用户体验的问题。我的解决方案是鼠标和键盘同时能选择关键字。用户可以使用键盘的箭头符号来定位候补词语,用回车来选取关键词语。同时也支持鼠标来选择关键词语。
这些功能可以需要很多JS的代码,但是对于一个认真制作,用心为用户着想的负责任的网站来说,是不能马虎的。
下面从网站的JS里面截取了一些相关的代码的片段,第一次写JS,可能不是写得很好,请大家多多帮忙指教。
var _wListInited = false;
//建议词语列表的选中项目
var ItemSelected = -1;
//检索建议词
var searchKey;
//上次的检索词
var PreSearchKey = "";
var InputText = "输入日文汉字,假名,罗马字,中文,或者拼音";
//onChange:检索词文本框的KeyUp事件
function onChange(aevent) {
searchKey = document.getElementById("ctl00_txtSearchWord").value;
if (searchKey == "") {
document.getElementById("jp_wordlist").style.display = "none";
_wListInited = false;
ItemSelected = -1;
return false;
}
if (navigator.userAgent.indexOf('Opera') > -1 && aevent.keyCode == 13) {
//Write Something Here
//Opera浏览器
}
if (!aevent) {
//IE,FF浏览器对应
aevent = window.event;
}
if (aevent.keyCode == 13 && ItemSelected != -1) {
document.getElementById("sug_item_" + ItemSelected).onclick();
return false;
}
if (aevent.keyCode != 40 && aevent.keyCode != 38) {
//上下箭头以外,1500ms之内没有操作,则调用AJAX
document.getElementById("jp_wordlist").style.display = "none";
_wListInited = false;
ItemSelected = -1;
if (searchKey != PreSearchKey) {
PreSearchKey = searchKey;
setTimeout("GetSug('" + searchKey + "')", 1500);
}
}
if (aevent.keyCode == 40 && _wListInited) {
//向下箭头
if (document.getElementById("sug_item_" + (ItemSelected + 1)) != null) {
//还有下一个项目时候
if (ItemSelected != -1) {
document.getElementById("sug_item_" + ItemSelected).className = "itemNormal";
}
ItemSelected += 1;
document.getElementById("sug_item_" + ItemSelected).className = "itemHighlight";
}
}
if (aevent.keyCode == 38 && _wListInited) {
//向上箭头
if (ItemSelected != -1) {
document.getElementById("sug_item_" + ItemSelected).className = "itemNormal";
ItemSelected -= 1;
}
if (ItemSelected != -1) {
document.getElementById("sug_item_" + ItemSelected).className = "itemHighlight";
}
}
}
//检索建议词语
function GetSug(ReadyToSearch) {
if (ReadyToSearch == searchKey) {
$.get("ASHX/GetWordList.ashx",
{ SearchKey: searchKey },
function(data) {
if (!(data.toString()=="" | data.toString()== "[object XMLDocument]")) {
//列表框表示
document.getElementById("jp_wordlist").innerHTML = data;
document.getElementById("jp_wordlist").style.display = "block";
_wListInited = true;
} else {
document.getElementById("jp_wordlist").style.display = "none";
_wListInited = false;
}
}
);
}
}
3.关于那个候选词语列表,怎么才能完美的出现在文本框的正下方,这个有的时候也是一个很头痛的问题。
特别是当今各种浏览器混乱的局面下,相同的HTML在不同浏览器中的表现各不相同,IE下面完美的出现在文本框下面的列表框,FF下面可能位置就不对了,有偏差了。这个问题的解决因人而异的,我也是调试了很久很久才搞定的(HTML比较菜)。
以上只是前台的代码的一些片段,如果想要完整的代码,直接到网站上看源代码和JS文件吧。。。。
既然前台的代码介绍了,最后就介绍一下后台的代码吧:
第一次使用ASHX这种代码,据说这个是专门用来做简单文字交互的。(有高手来说明一下这种代码吗,ASPX很菜)
using System;
using System.Web;
public class GetWordList : IHttpHandler {
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
if (context.Request["SearchKey"] != null)
{
String SearchKey;
SearchKey = context.Request["SearchKey"];
if (SearchKey == string.Empty) {
return;
}
if (!((SearchKey.IndexOf("%") > -1 | SearchKey.IndexOf("?") > -1))) {
SearchKey = clsJpHelper.ConvertRomaToKana(SearchKey);
System.Diagnostics.Debug.WriteLine("T=" + context.Request["SearchKey"]);
context.Response.Write(Core.GetWordListHTMLByMainIndex((SearchKey)));
}
}
context.Response.End();
}
public bool IsReusable {
get {
return false;
}
}
}
这样的代码估计人人都会写,这个文件就作为前台和后台的一个联络人了,由这个文件从后台检索数据,交还给前台。没有什么奇技淫巧。。。
总结一下:
1.网站用户体验是最重要的,有些功能用户使用不使用是一回事情,尽可能给用户多提供一些辅助功能是王道。同质化的网站竞争中,一个小细节决定成败。
2.技术尽量用简单的成熟的。不需要黑客才能写出来的代码。简单,简约,强壮就可以了。
有兴趣的写信给我 root#magicdict.com [convert # to @ ]
或者加MSN mynightelfplayer@hotmail.com