利用回发 实现一个简单的AutoComplete功能

把前段时间做的Auto Complete功能做了下整理 与各位分享

由于我们项目尽量避免使用AJAX,所以我们不得不重新写了套东西来实现Auto Complete。 还是感觉做成控件好一点。下面我来说下具体实现。

 基本原理就是利用回发机制,实现ICallbackEventHandler接口来达到页面不刷新 但是能与后台交换数据的功能。

 ASPX

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    
<title>Audto Complete</title>
    
<script src="autoComplete.js" type="text/javascript" language="javascript"></script>
</head>
<body>
    
<form id="form1" runat="server">
    
<div>
        
<script>
        function GetServerMethod(controlID)
        
{
           var message 
= controlID+","+document.getElementById(controlID).value;
           var context 
= controlID;           
          
<%=Page.ClientScript.GetCallbackEventReference(this"message""ShowAutoCompleteList""context")%>
        }

    
</script>
        
<asp:Label ID="lbl_Name" runat="server" Text="Product Name:"></asp:Label>
        
<asp:TextBox ID="txt_Name" runat="server" onkeyup="GetServerMethod(this.id);" autocomplete="off"></asp:TextBox>
    
</div>
    
</form>
</body>
</html>

 注意把TEXTBOX的autocomplete属性设为FALSE,不然会引起浏览器的自动填充功能。

我把对应要实现AutoComplete的控件ID和输入的值传到服务器端,message 保存ID和值,context保存ID,然后调用服务器方法。我们再来看下CS 文件

要实现接口 ICallbackEventHandler, 很简单


  ICallbackEventHandler Members

我们来看看RenderList方法是怎么写的

/// <summary>
        
/// Fill the auto complete with datasource and argument passed from aspx.
        
/// </summary>
        
/// <param name="eventArgument">value passed from aspx</param>
        
/// <returns>a string contains all the html source used by auto complete</returns>

        public string RenderList(string eventArgument)
        
{
            
string controlID = eventArgument.Split(',')[0];
            
string controlValue = eventArgument.Split(',')[1];
            
if (controlValue == string.Empty)
                
return string.Empty;
            StringBuilder strBuilder 
= new StringBuilder();

            
for (int i = 0; i < _dataSource.Count; i++)
            
{
                
if (_dataSource[i].ToString().StartsWith(controlValue, StringComparison.OrdinalIgnoreCase))
                
{
                    strBuilder.Append(
"<div onclick=""ValueFill(this, '" + controlID + "')"";'>");
                    strBuilder.Append(_dataSource[i].ToString());
                    strBuilder.Append(
"</div>");
                }

            }

            
return strBuilder.ToString();
        }

 

 主要就是通过控件上传来的值到服务器端的数据源中做比较 符合的就拿出来 生成到一个DIV中  最终生成一个符合的列表。


下面是写JS和样式


function ShowAutoCompleteList(retMessage, context)
{
   
var autoComplete=document.getElementById('AutoComplete');
   
if(retMessage=='')
   
{
       Reset(); 
return;
   }

   autoComplete.className
="AutoComplete";
   autoComplete.style.display
="block";
   autoComplete.style.left
=getX(document.getElementById(context))+"px";
   autoComplete.style.top
=getY(document.getElementById(context))+document.getElementById(context).offsetHeight+"px";
   autoComplete.style.width
=document.getElementById(context).offsetWidth+"px";
   autoComplete.innerHTML
=retMessage;
}


function ValueFill(obj,controlID)
{
    document.getElementById(controlID).value
=obj.innerHTML;
    Reset();   
}


function Reset()
{
    document.getElementById(
'AutoComplete').className="AutoCompleteHide";
    document.getElementById(
'AutoComplete').innerHTML=""; 
}


function getX(elem){
    
var x = elem.offsetLeft;
    
while(elem = elem.offsetParent){
        x 
= x + elem.offsetLeft;
    }

    
return x;
}


function getY(elem){
    
var y = elem.offsetTop;
    
while(elem = elem.offsetParent){
        y 
= y + elem.offsetTop;
    }

    
return y;
}


if (document.addEventListener)
   
{document.addEventListener('click',Reset, false);}
else

   
{document.attachEvent('onclick',Reset);}

 


/* AutoComplete Start */
.AutoComplete
{
    float
: left;
    z-index
: 1;
    position
: absolute;
    border-top-width
: 1px;
    border-right-width
: 1px;
    border-bottom-width
: 1px;
    border-left-width
: 1px;
    border-top-style
: solid;
    border-right-style
: solid;
    border-bottom-style
: solid;
    border-left-style
: solid;
    border-top-color
: #D8D8D8;
    border-right-color
: #D8D8D8;
    border-bottom-color
: #D8D8D8;
    border-left-color
: #D8D8D8;
    background-color
: White;
}


.AutoCompleteHide
{
    position
: absolute;
    visibility
: hidden;
}


.AutoComplete div:hover
{
    background-color
: #00bbff;
    cursor
:default;
}


/* AutoComplete End */


问题

其实没啥大的难度,利用接口+JS+样式。不过我这个auto complete还不是个控件,还有在出发回发事件上还有点小问题。

我是在 onkeyup的时候做的异步回发,这就是说在控件获得焦点,每次按键都会和服务器交互,这显然会加重服务器端压力,这以后要改的。

还有的就是没有加入上下按键选择功能,用起来有点不方便。

 

各位有啥好的建议也不妨介绍下 谢谢


posted @ 2009-03-29 16:47  八位机  阅读(1923)  评论(1编辑  收藏  举报