一个网站的诞生- 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很菜)

<%@ WebHandler Language="C#" Class="GetWordList" %>

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

网站地址 http://www.magicdict.com/


 

 

 

posted @ 2011-05-31 09:05  灰毛毛  阅读(1816)  评论(7编辑  收藏  举报