仿google的下拉提示框

  下面是代码:
先是建了一个用户控件 Suggest.ascx
前台代码:

 


  1<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Suggest.ascx.cs" Inherits="Suggest" %>
  2
  3<style type="text/css">
  4
  5.pnlSuggest
  6{
  7    border: #000000 1px solid;
  8    background-color: #FFFFFF;
  9    z-index: 9527;
 10    position: absolute;
 11    overflow-y: auto;
 12    overflow-x: hidden;
 13    text-overflow: clip;
 14}

 15
 16.pnlSuggest table
 17{
 18    width: 100%;
 19}

 20
 21.pnlSuggest tr
 22{
 23    width: 100%;
 24}

 25
 26.trmouseover
 27{
 28    width: 100%;
 29    background-color: #397CC3;
 30}

 31
 32.trmouseover td
 33{
 34    text-align: left;
 35    overflow: hidden;
 36    text-overflow: clip;
 37    background-color: #397CC3;
 38}

 39
 40.trmouseout
 41{
 42    width: 100%;
 43    background-color: #FFFFFF;
 44}

 45
 46.trmouseout td
 47{
 48    text-align: left;
 49    overflow: hidden;
 50    text-overflow: clip;
 51    background-color: #FFFFFF;
 52}

 53
 54.txtValues
 55{
 56    display: none;
 57}

 58
 59.dataSource
 60{
 61    display: none;
 62}

 63
 64.hiddentd
 65{
 66    display: none;
 67}

 68
 69.hiddenValues
 70{
 71    display: none;
 72}

 73
 74
</style>
 75
 76<script language="javascript" type="text/javascript">
 77
 78//为string对象添加一个清除前后空格的属性
 79String.prototype.trim = function()
 80{
 81    return this.replace(new RegExp("(^[//s]*)|([//s]*$)""g"), "");
 82}
;
 83
 84//显示下拉信息
 85function ShowSuggest(objInputText)
 86{
 87    objInputText.onkeyup = ControlSuggest;
 88    
 89    objInputText.onblur = RemoveSuggest;
 90    
 91    var oldValue = objInputText.parentElement.getElementsByTagName("h6")[0];
 92    
 93    //对提示框的控制
 94    function ControlSuggest()
 95    {
 96        var ie = (document.all)?true:false;
 97        if(ie)
 98        {
 99            var keycode = event.keyCode;
100            var txtvalues = objInputText.value.trim().split(";");
101            
102            if!CheckSuggest() && txtvalues[txtvalues.length-1!= oldValue.innerText.trim())
103            {
104                CreateSuggest();
105                return ;
106            }

107            
108            if(keycode == 32 && txtvalues[txtvalues.length-1!= oldValue.innerText.trim())
109            {
110                CreateSuggest();
111                return ;
112            }

113            
114            //按向下创建提示
115            if(!CheckSuggest() && txtvalues[txtvalues.length-1].length !=0 && keycode == 40)
116            {//文本框有内容,提示不存在,向下
117                CreateSuggest();
118                return;
119            }

120            
121            //当删除的时候,参量要初始化
122            if(keycode == 8 && txtvalues[txtvalues.length-1].length == 0)
123            {
124                DeleteSuggest();
125                oldValue.innerText = "";
126                return ;
127            }

128            
129            if(CheckSuggest())
130            {
131                var inputIndex = document.getElementById("inputIndex");
132                var selectIndex = Number(inputIndex.value);
133                
134                //排除上下控制的值操作外,其他任何值改变都要去创建提示框
135                if( selectIndex < 0 && txtvalues[txtvalues.length-1!= oldValue.innerText)
136                {
137                    CreateSuggest();
138                    return ;
139                }

140                
141                if(keycode == 40)
142                {//向下
143                    ChangeSelection(false);
144                    return ;
145                }

146                
147                if(keycode == 38)
148                {//向上
149                    ChangeSelection(true);
150                    return ;
151                }

152                
153                if(keycode == 46 || keycode == 27)
154                {//del
155                    DeleteSuggest();
156                    oldValue.innerText = "";
157                    return ;
158                }

159                
160                var panelSuggest = document.getElementById("divSuggestPanel");
161                var tb = panelSuggest.getElementsByTagName("table")[0];
162
163                if(keycode == 13)
164                {//回车
165                    if(selectIndex > -1 && txtvalues[txtvalues.length-1!= oldValue.innerText)
166                    {
167                        CreateSuggest();
168                        return ;
169                    }

170                    RemoveSuggest();
171                    return ;
172                }

173                
174            }

175            
176            if(txtvalues[txtvalues.length-1!= oldValue.innerText)
177            {//当上面的条件都筛选后,只要值发生改变就创建下拉提示
178                CreateSuggest();
179                return ;
180            }

181        }

182    }

183    
184    //删除提示前对文本做相关操作
185    function RemoveSuggest()
186    {
187        if(CheckSuggest())
188        {
189            var panelSuggest = document.getElementById("divSuggestPanel");
190            var inputIndex = document.getElementById("inputIndex");
191            
192            var txtvalues = objInputText.value.trim().split(";");
193            
194            if( CheckActiveElement(panelSuggest) || event.keyCode == 13)
195            {
196                //做个判断,判断当前活动对象 是不是TD,是的话就执行下面的操作,不是的话就不做操作,或者把文本框作为当前活动
197                if(CheckActiveElement(panelSuggest) && document.activeElement.tagName != "TD")
198                {
199                    objInputText.focus();
200                    return ;
201                }

202                
203                //得到选定的值
204                var selectIndex = Number(inputIndex.value);
205                if(selectIndex >= 0)
206                {
207                    var tb = panelSuggest.getElementsByTagName("table")[0];
208                    txtvalues[txtvalues.length-1= tb.rows[selectIndex].cells[0].innerText;
209                    objInputText.value = GetValues(txtvalues);
210                }

211            }

212            
213            document.body.removeChild(inputIndex);
214            document.body.removeChild(panelSuggest);
215            oldValue.innerText = "";
216        }

217        else
218        {
219            return ;
220        }

221    }

222    
223    //删除提示的方法,不对文本做任何操作
224    function DeleteSuggest()
225    {
226        if(CheckSuggest())
227        {
228            var panelSuggest = document.getElementById("divSuggestPanel");
229            var inputIndex = document.getElementById("inputIndex");
230            document.body.removeChild(inputIndex);
231            document.body.removeChild(panelSuggest);
232        }

233    }

234    
235    //加载提示框
236    function CreateSuggest()
237    {
238        var txtvalues = objInputText.value.trim().split(";");
239        
240        //提示框存在,而且文本框值与上次的输入不同时,才进行下面的加载工作
241        if(CheckSuggest())
242        {
243            if( oldValue.innerText.trim() == txtvalues[txtvalues.length-1].trim())
244            {
245                return ;
246            }

247            else
248            {
249                DeleteSuggest();
250            }

251        }

252        
253        if(CheckSuggest() && txtvalues[txtvalues.length-1].trim().length ==0)
254        {//提示框存在,但是文本框没有内容,这时删除提示框
255            DeleteSuggest();
256            oldValue.innerText = "";
257            return ;
258        }

259        
260        //如果输入为空格,就退出
261        if(txtvalues[txtvalues.length-1].trim().length == 0)
262        {
263            return ;
264        }
 
265        
266        //从数据源中取数据
267        var suggestList = GetSuggestList();
268        
269        if(suggestList == null||suggestList.length < 1)
270        {//对传入的数组进行判断,为空或者列表为0就退出
271            DeleteSuggest();                                  //开始的输入有提示,后面的输入可能没有提示,所以数据源为空时要尝试删除提示
272            oldValue.innerText = "";
273            return ;
274        }

275        
276        oldValue.innerText = txtvalues[txtvalues.length-1];              //以上条件都符合,根据数据源来创建数据
277        
278        var inputIndex = document.createElement("input");     //用隐藏控件来做索引的保存
279        inputIndex.type = "hidden";
280        inputIndex.id = "inputIndex";
281        inputIndex.value = -1;
282        
283        var suggest = "";                                     //根据数据源来写div提示信息
284        suggest += "<table>";
285        for(var nIndex = 0; nIndex < suggestList.length; nIndex++)
286        {
287            suggest += "<tr οnmοuseοver=/" for(var n=0;n<this.parentElement.rows.length;n++){this.parentElement.rows[n].className='trmouseout';};this.className='trmouseover';var inputIndex = document.getElementById('inputIndex');inputIndex.value = this.rowIndex; /" οnmοuseοut=/"this.className='trmouseout';/"  >";
288            suggest += suggestList[nIndex];
289            suggest += "</tr>";
290        }

291        suggest += "</table>";
292        
293        var panelSuggest = document.createElement("div");                //创建装提示框的容器div
294        
295        panelSuggest.id = "divSuggestPanel";
296        panelSuggest.className = "pnlSuggest";                           //设置对象的类
297        panelSuggest.style.width = objInputText.clientWidth + "px";      //设置对象的宽度,与文本框宽度相同
298        panelSuggest.style.top = (GetPosition()[0+ objInputText.offsetHeight + 1+ "px";
299        panelSuggest.style.left = GetPosition()[1+ "px";
300        panelSuggest.innerHTML = suggest;
301        
302        document.body.appendChild(panelSuggest);                         //把提示框和索引控件添加进来        
303        document.body.appendChild(inputIndex);
304        
305        //判断显示条数的多少,多于10条就用滚动条操作
306        if(suggestList.length > 10)
307        {
308            var h = panelSuggest.getElementsByTagName("tr")[1].offsetHeight;
309            panelSuggest.style.height = (h * 10+ "px";
310            panelSuggest.style.width = (objInputText.clientWidth + 20+ "px";
311        }

312        
313    }

314    
315    //更换选项
316    function ChangeSelection(isup)
317    {
318
319        if(CheckSuggest())
320        {
321            var txtvalues = objInputText.value.trim().split(";");
322            
323            var inputIndex = document.getElementById("inputIndex");                 //得到索引的值
324            var selectIndex = Number(inputIndex.value);
325            
326            var panelSuggest = document.getElementById("divSuggestPanel");          //得到提示框
327            var tb = panelSuggest.getElementsByTagName("table")[0]; 
328            var maxIndex = tb.rows.length - 1;                                      //提示信息的最大索引
329            
330            if(isup)
331            {//向上
332                if(selectIndex >= 0)                                                //索引不能为负
333                {
334                    tb.rows[selectIndex].className = "trmouseout";
335                    selectIndex--;
336                    if(selectIndex >= 0)
337                    {
338                        tb.rows[selectIndex].className = "trmouseover";
339                    }

340                }

341            }

342            else
343            {
344                if(selectIndex < maxIndex)                                          //大于等于最大索引就不做任何操作
345                {
346                    if(selectIndex >= 0)
347                    {
348                        tb.rows[selectIndex].className = "trmouseout";
349                    }

350                    selectIndex++;
351                    tb.rows[selectIndex].className = "trmouseover";
352                }

353            }

354            
355            inputIndex.value = selectIndex;
356            //控制滚动条的上下
357            if(selectIndex >= 0)
358            {
359                if(tb.rows[selectIndex].offsetTop < panelSuggest.scrollTop)
360                {
361                    panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop;
362                }

363                if(tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight > panelSuggest.scrollTop + panelSuggest.offsetHeight)
364                {
365                    panelSuggest.scrollTop = tb.rows[selectIndex].offsetTop + tb.rows[selectIndex].offsetHeight - panelSuggest.offsetHeight;
366                }

367            }

368            
369        }

370        
371    }

372    
373    //判断活动对象是否为obj对象的从属对象
374    function CheckActiveElement(obj)
375    {
376        var isAe = false;
377        var objtemp = document.activeElement;
378        while(objtemp != null)
379        {
380            if(objtemp == obj)
381            {
382                isAe = true;
383                break;
384            }

385            objtemp = objtemp.parentElement;
386        }

387        return isAe;
388    }

389    
390    //检查提示框是否存在
391    function CheckSuggest()
392    {
393        var panelSuggest = document.getElementById("divSuggestPanel");
394        if(panelSuggest == null)
395        {
396            return false;
397        }

398        else
399        {
400            return true;
401        }

402    }

403    
404    //获取文本框的位置
405    function GetPosition()
406    {
407        var top = 0,left = 0;
408        var obj = objInputText;
409        do 
410        {
411            top += obj.offsetTop;         //距离顶部
412            left += obj.offsetLeft;       //距离左边
413        }

414        while (obj = obj.offsetParent);
415        
416        var arr = new Array();
417        arr[0= top;
418        arr[1= left;
419        return arr; 
420    }

421    
422    //得到提示数据
423    function GetSuggestList()
424    {
425        var txtvalues = objInputText.value.trim().split(";");
426        var txtfield = txtvalues[txtvalues.length-1];
427        var hiddenvaluefield = objInputText.parentElement.getElementsByTagName("h2")[0].innerText;
428        var showtextfield = objInputText.parentElement.getElementsByTagName("h3")[0].innerText;
429        var procedurename = objInputText.parentElement.getElementsByTagName("h4")[0].innerText;
430        var condition = objInputText.parentElement.getElementsByTagName("h5")[0].innerText;
431        var suggestlist = Suggest.GetSuggestData(txtfield,showtextfield,procedurename,condition).value;
432        return suggestlist;
433    }

434    
435    //得到文本框的显示值
436    function GetValues(values)
437    {
438        var txtvalue="";
439        for(var n=0;n<values.length;n++)
440        {
441            if(values[n].trim().length==0)
442            {
443                continue;
444            }

445            txtvalue+=values[n]+";";
446        }

447        return txtvalue;
448    }

449    
450}

451
452
</script>
453
454<div>
455    <input type="text" runat="server" id="txtInput" name="txtInput" onkeydown="ShowSuggest(this);" style="width: 320px" autocomplete="off" />
456    <h2 id="hneedfield" runat="server" class="hiddenValues"></h2>
457    <h3 id="hshowfield" runat="server" class="hiddenValues"></h3>
458    <h4 id="hprocedurename" runat="server" class="hiddenValues"></h4>
459    <h5 id="hhashvalue" runat="server" class="hiddenValues"></h5>
460    <h6 class="hiddenValues" style="display: none;"></h6>
461</div>
462


后台代码:

 

 


  1using System;
  2using System.Data;
  3using System.Configuration;
  4using System.Collections;
  5using System.Web;
  6using System.Web.Security;
  7using System.Web.UI;
  8using System.Web.UI.WebControls;
  9using System.Web.UI.WebControls.WebParts;
 10using System.Web.UI.HtmlControls;
 11using System.Collections.Generic;
 12using System.Data.SqlClient;
 13using IIP.Data.SQLHelper;
 14
 15/// <summary>
 16/// 作者:李宏武
 17/// 时间:2008年7月18号
 18/// 公司:
 19/// 项目:
 20/// 模块:仿google下拉提示的文本输入框控件
 21/// 修改记录:无
 22/// 使用说明:调用该控件,要设置控件的相关属性:
 23///           显示提示的筛选字段名 TextField
 24///           查询数据的存储过程名 Procedurename
 25///           存储过程的各项参数   ProcedureParams(Hashtable类型,key值放参数名,value值为参数值)
 26///           还可以通过下面的方法,设置域的值:
 27///           List<string> showFields    要下拉提示的相关信息  AddShowFields(string field)方法添加
 28///           设置好上面的信息后就可以使用了,要得到文本框信息,通过属性Text得到
 29///           要取得与文本信息相匹配的隐藏信息,也就是与hiddenFields对应的信息,通过属性Values得到
 30/// </summary>

 31public partial class Suggest : System.Web.UI.UserControl
 32{
 33    private string textField;
 34
 35    /// <summary>
 36    /// 设置要显示提示的筛选字段名
 37    /// </summary>

 38    public string TextField
 39    {
 40        set { textField = value; }
 41    }

 42
 43    private string valueField;
 44
 45    /// <summary>
 46    /// 设置要得到的唯一性标识的字段名
 47    /// </summary>

 48    public string ValueField
 49    {
 50        set { valueField = value; }
 51    }

 52
 53    private string procedurename;
 54
 55    /// <summary>
 56    /// 设置查询数据的存储过程名
 57    /// </summary>

 58    public string Procedurename
 59    {
 60        set { procedurename = value; }
 61    }

 62
 63    private Hashtable procedureParams = new Hashtable();
 64
 65    /// <summary>
 66    /// 设置存储过程的各项参数
 67    /// </summary>

 68    public Hashtable ProcedureParams
 69    {
 70        set { procedureParams = value; }
 71    }

 72
 73    private List<string> showFields = new List<string>();
 74
 75    /// <summary>
 76    /// 添加显示内容的字段
 77    /// </summary>
 78    /// <param name="field">字段名</param>

 79    public void AddShowFields(string field)
 80    {
 81        showFields.Add(field);
 82    }

 83
 84    /// <summary>
 85    /// 得到文本框的值
 86    /// </summary>

 87    public string Text
 88    {
 89        get 
 90        {
 91            string[] texts = txtInput.Value.Split(new string[] ";" }, StringSplitOptions.None);
 92            DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);
 93            string txtvalue = "";
 94            foreach (string text in texts)
 95            {
 96                DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[] "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0+ " = '" + text + "'");
 97                if (drs.Length > 0)
 98                {
 99                    txtvalue += text + ",";
100                }

101            }

102            return txtvalue;
103        }

104    }

105
106    /// <summary>
107    /// 得到与文本框值匹配的信息
108    /// </summary>

109    public string Values
110    {
111        get
112        {
113            string[] texts = txtInput.Value.Split(new string[] ";" }, StringSplitOptions.None);
114            DataTable dt = GetDataSourse(this.hprocedurename.InnerText, this.hhashvalue.InnerText);
115            string value = "";
116            foreach (string text in texts)
117            {
118                DataRow[] drs = dt.Select(this.hshowfield.InnerText.Split(new string[] "$h,w$" }, StringSplitOptions.RemoveEmptyEntries)[0+ " = '" + text + "'");
119                if (drs.Length > 0)
120                {
121                    value += drs[0][this.hneedfield.InnerText.Trim()].ToString() + ",";
122                }

123            }

124            return value;
125        }

126    }

127
128    /// <summary>
129    /// 得到数据源
130    /// </summary>
131    /// <param name="procedurename">存储过程名</param>
132    /// <param name="condition">存储过程参数</param>
133    /// <returns>查询数据源</returns>

134    private DataTable GetDataSourse(string procedurename, string condition)
135    {
136        //从数据源得到数据
137        string[] keyandvalue = condition.Split(new string[] "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);
138
139        SqlParameter[] commandparameters;
140        if (keyandvalue.Length == 0)
141        {
142            commandparameters = null;
143        }

144        else
145        {
146            commandparameters = new SqlParameter[keyandvalue.Length];
147            for (int i = 0; i < commandparameters.Length; i++)
148            {
149                string[] tempvalue = keyandvalue[i].Split(new string[] "$h,57,w$" }, StringSplitOptions.None);
150                commandparameters[i] = new SqlParameter(tempvalue[0], SqlDbType.VarChar, 500);
151                commandparameters[i].Value = tempvalue[1];
152            }

153        }

154
155        DataSet ds = SqlHelper.ExecuteDataset(Comm.connectionString, CommandType.StoredProcedure, procedurename, commandparameters);
156        if (ds == null || ds.Tables[0== null)
157        {
158            return null;
159        }

160        else
161        {
162            return ds.Tables[0];
163        }

164    }

165
166    /// <summary>
167    /// 根据输入内容,得到数据
168    /// </summary>
169    /// <param name="txtfield">显示文本</param>
170    /// <param name="showtextfield">下拉提示的相关字段</param>
171    /// <param name="procedurename">存储过程名</param>
172    /// <param name="condition">存储过程参数</param>

173    [Ajax.AjaxMethod]
174    public string[] GetSuggestData(string txtfield, string showtextfield, string procedurename, string condition)
175    {
176        
177        //数据的要显示字段和要相关得到数值的字段
178        string[] shows = showtextfield.Split(new string[] "$h,w$" }, StringSplitOptions.RemoveEmptyEntries);
179
180        //数据的筛选
181        DataTable dt = GetDataSourse(procedurename, condition);
182        if (dt == null)
183        {
184            return null;
185        }

186        DataRow[] drs = dt.Select(shows[0+ " like '%" + txtfield + "%'");
187        if (drs.Length == 0)
188        {
189            return null;
190        }

191
192        //将数据做为显示流
193        List<string> fields = new List<string>();
194
195        for (int j = 0; j < shows.Length; j++)
196        {
197            fields.Add(shows[j]);
198        }

199
200        string[] tbs = new string[drs.Length];
201        int count = 0;
202        foreach (DataRow dr in drs)
203        {
204            foreach (string item in fields)
205            {
206                tbs[count] += "<td>" + dr[item].ToString() + "</td>";
207            }

208            count++;
209        }

210        return tbs;
211    }

212
213    /// <summary>
214    /// 页面的相关信息的保存
215    /// </summary>

216    private void BindValue()
217    {
218        //页面中加上与文本输入相关的有下拉提示的字段
219        this.hshowfield.InnerText = this.textField;
220        int i = 0;
221        foreach (string item in showFields)
222        {
223            this.hshowfield.InnerText += "$h,w$";
224            this.hshowfield.InnerText += item;
225            i++;
226        }

227
228        //页面中加上查询数据源的存储过程
229        this.hprocedurename.InnerText = this.procedurename;
230
231        //页面中加上与存储过程匹配的参数
232        this.hhashvalue.InnerText = "";
233        if (procedureParams != null && procedureParams.Count > 0)
234        {
235            i = 0;
236            foreach (DictionaryEntry temp in procedureParams)
237            {
238                if (i != 0)
239                {
240                    this.hhashvalue.InnerText += "$h,w$";
241                }

242                this.hhashvalue.InnerText += temp.Key.ToString() + "$h,57,w$" + temp.Value.ToString();
243                i++;
244            }

245        }

246
247        //唯一标识的字段名
248        this.hneedfield.InnerText = this.valueField;
249    }

250
251    protected void Page_Load(object sender, EventArgs e)
252    {
253        Ajax.Utility.RegisterTypeForAjax(typeof(SearchText));
254        if (!IsPostBack)
255        {
256            BindValue();
257        }

258    }

259}

260

 

然后在aspx页面就可以拖这个控件来用,不过在其page_load方法中,要对控件的两个控件进行设置,不然是不会有提示框弹出的,因为数据源都没有。呵呵

效果是仿google做的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值