zoukankan      html  css  js  c++  java
  • 简易搜索智能提示文本框

      本程序仿照Google搜索自动完成功能,当用户在搜索文本框中输入搜索关键字时,利用Ajax请求服务器数据库获取相匹配数据返回,然后以列表方式显示在搜索文本框的下方。

    界面截图如下:

    一、对搜索文本框的简单封装:

     1 using System;
    2 using System.Text;
    3 using System.Web.UI.WebControls;
    4 using System.ComponentModel;
    5 using System.IO;
    6 using System.Collections;
    7
    8 namespace MyControls
    9 {
    10 public class AutoCompleteTextBox : TextBox
    11 {
    12 /// <summary>
    13 /// 设置或获取资源文件夹目录
    14 /// </summary>
    15 [Bindable(true)]
    16 [Category("搜索")]
    17 [Description("设置或获取资源文件夹目录")]
    18 public String ClientScriptPath
    19 {
    20 get
    21 {
    22 String s = (String)ViewState["ClientScriptPath"];
    23 return ((s == null) ? String.Empty : s);
    24 }
    25
    26 set
    27 {
    28 ViewState["ClientScriptPath"] = value;
    29 }
    30 }
    31
    32 protected override void OnPreRender(EventArgs e)
    33 {
    34 string strJsPath = base.ResolveUrl(Path.Combine(this.ClientScriptPath, @"SearchControlIntelligent.js"));
    35 if (!Page.ClientScript.IsClientScriptBlockRegistered(this.GetType(), "SearchControlIntelligentScript"))
    36 {
    37 Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "SearchControlIntelligentScript", "<script type=\"text/javascript\" src=\"" + strJsPath + "\"></script>", false);
    38 }
    39
    40 StringBuilder strInitScript = new StringBuilder(50);
    41 strInitScript.Append("<script type=\"text/javascript\">");
    42 strInitScript.AppendFormat("initQueryCode('{0}')", this.ClientID);
    43 strInitScript.Append("</script>");
    44
    45 if (!Page.ClientScript.IsStartupScriptRegistered(this.GetType(), "InitScript" + this.UniqueID))
    46 {
    47 Page.ClientScript.RegisterStartupScript(this.GetType(), "InitScript" + this.UniqueID, strInitScript.ToString());
    48 }
    49 base.OnPreRender(e);
    50 }
    51
    52 protected override void OnLoad(EventArgs e)
    53 {
    54 AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProSearchService));
    55 base.OnLoad(e);
    56 }
    57 }
    58 }

    二、通过搜索字符获取数据库中相匹配条目

     1 using System;
    2 using System.Data.SqlClient;
    3 using System.Data;
    4 using System.Configuration;
    5
    6 namespace MyControls
    7 {
    8 [AjaxPro.AjaxNamespace("AjaxProSearchService")]
    9 public class AjaxProSearchService
    10 {
    11 public static string CONN_STRING = ConfigurationManager.AppSettings["SqlServerConnectionString"];
    12
    13 [AjaxPro.AjaxMethod]
    14 public static DataSet GetKeywordByChar(string key)
    15 {
    16 if (key == null || key.Length == 0) return null;
    17 using (SqlConnection con = new SqlConnection(CONN_STRING))
    18 {
    19 SqlCommand comd = new SqlCommand(string.Format("select Keyword from AutoCompleteSearch where Keyword like '%{0}%'", key), con);
    20 SqlDataAdapter sqlDa = new SqlDataAdapter(comd);
    21 con.Open();
    22 DataSet ds = new DataSet();
    23 sqlDa.Fill(ds);
    24 return ds;
    25 }
    26 }
    27 }
    28 }

    三、将匹配的条目以列表方式显示在搜索文本框下方,添加键盘和鼠标的响应操作

      1 var DIV_BG_COLOR = "#FFFFFF"; //智能提示框背景颜色
    2 var DIV_HIGHLIGHT_COLOR = "#B4CCEB" //智能提示框中被选中条目背景颜色
    3 var DIV_FONT = "Arial"; //智能提示框中文字颜色
    4 var DIV_PADDING = "2px"; //智能提示框中条目padding
    5 var DIV_BORDER = "1px solid #020086"; //智能提示框边框颜色
    6 var queryField; //搜索文本框
    7 var divName; //始智能提示div的id
    8 var lastVal = ""; //上次搜索的关键字
    9 var globalDiv; //智能提示框div
    10 var divFormatted = false; //标示智能提示框div是否已被设置样式
    11
    12 /*
    13 给搜索文本框注册事件
    14 queryFiledId:搜索框id
    15 */
    16 function initQueryCode(queryFiledId) {
    17 queryField = document.getElementById(queryFiledId);
    18 queryField.onblur = hideDiv;
    19 queryField.onkeydown = keypressHandler;
    21 divName = "querydiv"; //初始智能提示div的id
    22 setTimeout("mainLoop()", 100);
    23 }
    24
    25 /*
    26 获取智能提示框div
    27 divID:智能提示框div的id
    28 */
    29 function getDiv(divID) {
    30 if (!globalDiv) {
    31 if (!document.getElementById(divID)) {
    32 var newNode = document.createElement("div");
    33 newNode.setAttribute("id", divID);
    34 document.body.appendChild(newNode);
    35 }
    36 globalDiv = document.getElementById(divID); //将智能提示框div的引用保存到globalDiv变量中
    37 var x = queryField.offsetLeft;
    38 var y = queryField.offsetTop + queryField.offsetHeight;
    39 var parent = queryField;
    40 while (parent.offsetParent) {
    41 parent = parent.offsetParent;
    42 x += parent.offsetLeft;
    43 y += parent.offsetTop;
    44 }
    45 if (!divFormatted) {
    46 globalDiv.style.backgroundColor = DIV_BG_COLOR;
    47 globalDiv.style.fontFamily = DIV_FONT;
    48 globalDiv.style.padding = DIV_PADDING;
    49 globalDiv.style.border = DIV_BORDER;
    50 globalDiv.style.width = queryField.style.width;
    51 globalDiv.style.fontSize = "90%";
    52 globalDiv.style.position = "absolute";
    53 globalDiv.style.left = x + "px";
    54 globalDiv.style.top = y + "px";
    55 globalDiv.style.visibility = "hidden";
    56 globalDiv.style.zIndex = 10000;
    57 divFormatted = true;
    58 }
    59 }
    60 return globalDiv;
    61 }
    62
    63 /*
    64 显示智能提示div
    65 resultArray:提示结果集
    66 */
    67 function showQueryDiv(resultArray) {
    68 var div = getDiv(divName); //获取智能提示div,并移除其中条目
    69 while (div.childNodes.length > 0) {
    70 div.removeChild(div.childNodes[0]);
    71 }
    72 //每一个提示条目放在div中
    73 for (var i = 0; i < resultArray.length; i++) {
    74 var itemDiv = document.createElement("div");
    75 itemDiv.style.cursor = "pointer";
    76 itemDiv.style.padding = "2px 0px 2px 0px";
    77 itemDiv.style.width = div.style.width;
    78 _unhighlightResult(itemDiv); //给每一个条目赋背景色
    79 //鼠标按下,将当前条目文字赋给搜索框,关闭智能提示div
    80 itemDiv.onmousedown = selectResult;
    81 //鼠标经过条目设置其高亮
    82 itemDiv.onmouseover = highlightResult;
    83 //鼠标离开,取消高亮
    84 itemDiv.onmouseout = unhighlightResult;
    85 //每一提示条目的文字放在span中
    86 var value = document.createElement("span");
    87 value.className = "value";
    88 value.style.textAlign = "left";
    89 value.style.fontWeight = "bold";
    90 value.innerHTML = resultArray[i];
    91 itemDiv.appendChild(value);
    92 div.appendChild(itemDiv);
    93 }
    94 showDiv(resultArray.length > 0);
    95 }
    96
    97 function selectResult() {
    98 _selectResult(this);
    99 }
    100
    101 /*
    102 选中条目,关闭智能提示框
    103 item:被选中的条目
    104 */
    105 function _selectResult(item) {
    106 var spans = item.getElementsByTagName("span");
    107 if (spans) {
    108 for (var i = 0; i < spans.length; i++) {
    109 if (spans[i].className == "value") {
    110 queryField.value = spans[i].innerHTML;
    111 lastVal = val = escape(queryField.value);
    112 mainLoop();
    113 queryField.focus();
    114 showDiv(false);
    115 return;
    116 }
    117 }
    118 }
    119 }
    120
    121 function highlightResult() {
    122 _highlightResult(this);
    123 }
    124
    125 /*
    126 设置条目高亮(设置背景色突出显示)
    127 item:设置高亮的条目
    128 */
    129 function _highlightResult(item) {
    130 item.style.backgroundColor = DIV_HIGHLIGHT_COLOR;
    131 }
    132
    133 function unhighlightResult() {
    134 _unhighlightResult(this);
    135 }
    136
    137 /*
    138 取消高亮(还原背景色)
    139 item:取消高亮的条目
    140 */
    141 function _unhighlightResult(item) {
    142 item.style.backgroundColor = DIV_BG_COLOR;
    143 }
    144
    145 /*
    146 显示智能提示框
    147 isShow:是否显示bool值
    148 */
    149 function showDiv(isShow) {
    150 var div = getDiv(divName);
    151 if (isShow) {
    152 div.style.visibility = "visible";
    153 } else {
    154 div.style.visibility = "hidden";
    155 }
    156 }
    157
    158 function hideDiv() {
    159 showDiv(false);
    160 }
    161
    162 /*
    163 鼠标按下事件处理
    164 e:事件对象
    165 */
    166 function keypressHandler(e) {
    167 var div = getDiv(divName);
    168 if (div.style.visibility == "hidden") {
    169 return true;
    170 }
    171 var key = -1;
    172 if (window.event) {
    173 key = window.event.keyCode; //IE下获取键值
    174 } else {
    175 key = e.which; ////FireFox,其它
    176 }
    177 var KEYUP = 38; //上方向键
    178 var KEYDOWN = 40; //下方向键
    179 var KEYENTER = 13; //回车键
    180 var KEYTAB = 9; //tab键
    181 if (key != KEYUP && key != KEYDOWN && key != KEYENTER && key != KEYTAB) {
    182 return true;
    183 }
    184 var selNum = getSelectedItemNum(div); //获取当前处于选中状态的条目序号
    185 var selItem = setSelectedItem(div, selNum);
    186 if (key == KEYENTER || key == KEYTAB) {
    187 if (selItem) {
    188 _selectResult(selItem);
    189 }
    190 e.cancelBubble = true;
    191 return false;
    192 } else {
    193 if (key == KEYUP) {
    194 selItem = setSelectedItem(div, selNum - 1);
    195 }
    196 if (key == KEYDOWN) {
    197 selItem = setSelectedItem(div, selNum + 1);
    198 }
    199 if (selItem) {
    200 _highlightResult(selItem);
    201 }
    202 }
    203 showDiv(true);
    204 return true;
    205 }
    206
    207 /*
    208 获取选中条目的序号
    209 div:智能提示框div
    210 */
    211 function getSelectedItemNum(div) {
    212 var items = div.getElementsByTagName("div");
    213 if (items) {
    214 for (var i = 0; i < items.length; i++) {
    215 //没有选中条目都被设置与提示框颜色相同
    216 if (items[i].style.backgroundColor != div.style.backgroundColor) {
    217 return i;
    218 }
    219 }
    220 }
    221 return -1;
    222 }
    223
    224 /*
    225 设置条目为选中状态
    226 div:智能提示框div,itemNum:条目序号
    227 */
    228 function setSelectedItem(div, itemNum) {
    229 var thisDiv;
    230 var divs = div.getElementsByTagName("div");
    231 if (divs) {
    232 for (var i = 0; i < divs.length; i++) {
    233 if (i == itemNum) {
    234 _highlightResult(divs[i]);
    235 thisDiv = divs[i];
    236 }
    237 else {
    238 _unhighlightResult(divs[i]);
    239 }
    240 }
    241 }
    242 return thisDiv;
    243 }
    244
    245 var mainLoop = function() {
    246 var val = escape(queryField.value);
    247 if (lastVal != val) {
    248 var response = AjaxProSearchService.GetKeywordByChar(val);
    249 var datatable = response.value.Tables[0];
    250 var arrayKey = new Array();
    251 if (datatable.Rows.length > 0) {
    252 for (var i = 0; i < datatable.Rows.length; i++) {
    253 arrayKey.push(datatable.Rows[i].Keyword);
    254 }
    255 }
    256 showQueryDiv(arrayKey);
    257 lastVal = val;
    258 }
    259 setTimeout("mainLoop()", 100);
    260 return true;
    261 }

    需要说明一下的是,程序中用到了AjaxPro这个Ajax框架,AjaxPro支持通过javascript访问服务端方法。其使用方法很简单。

    1、添加对AjaxPro.2.dll的引用。

    2、在Web.config中注册该组件的处理程序,代码如下:

        <httpHandlers>
    <!--AjaxPro.2.dll-->
    <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory,AjaxPro.2"/>
    ……
    </httpHandlers>

    3、在使用AjaxPro组件的页面Page_Load事件中注册类类型:

      AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProSearchService));//AjaxProSearchService为使用AjaxPro组件的页面类名

    4、使用实例:
      服务器端方法的申明:

            [AjaxPro.AjaxMethod]  //必不可少
    public static DataSet GetKeywordByChar(string key)
    {
    ……
    }

      客服javascript端调用:

       //AjaxProSearchService:访问的服务器端方法的类名,val:与服务器端方法参数保持一致
    var
    response = AjaxProSearchService.GetKeywordByChar(val);

    很简单的一个功能,还有很多细节以后慢慢完善。



  • 相关阅读:
    记录一次电话面试
    记录一次git合并
    HTML通用属性与常见标签
    位运算的应用
    HTML总结
    前端MVC
    常用软件
    docker常用命令
    composer install(update)时出现killed
    优化小技巧:该怎么识别百度蜘蛛呢
  • 原文地址:https://www.cnblogs.com/psforever/p/2282989.html
Copyright © 2011-2022 走看看