我平時(shí)的軟件開發(fā)中,信息的搜索是經(jīng)常碰到的,增加搜索關(guān)鍵字提示是提高用戶體驗(yàn)的一種很好的辦法。今天就介紹下在ASP.NET如何利用AJAX來實(shí)現(xiàn)搜索的信息提示!
1.需要了解的一些知識(shí)點(diǎn)
(1)AJAX對(duì)象不同瀏覽器的創(chuàng)建
不同的瀏覽器對(duì)AJAX(XMLHttpRequest)對(duì)象的實(shí)現(xiàn)是不一樣的,例如IE瀏覽器是通過ActiveX控件來實(shí)現(xiàn)AJAX對(duì)象。而其他一些 瀏覽器比如火狐,它將AJAX對(duì)象實(shí)現(xiàn)成了一個(gè)瀏覽器內(nèi)部的對(duì)象叫XMLHttpRequest,所以不同的瀏覽器創(chuàng)建AJAX對(duì)象的方式也就不同,那么 我們來看看不同瀏覽器之間創(chuàng)建AJAX對(duì)象的方式:
在IE瀏覽器下面的創(chuàng)建:
//IE瀏覽器
try {
//IE5.0
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
//IE5.5 以上版本
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
在火狐瀏覽器下面的創(chuàng)建:
//火狐, Safari 等瀏覽器
httpRequest = new XMLHttpRequest();
多瀏覽器AJAX對(duì)象創(chuàng)建函數(shù):
function createAjaxObj() {
var httpRequest = false;
//判斷是否包含XMLHttpRequest對(duì)象 PS:將來IE高也有可能繼承次對(duì)象
if (window.XMLHttpRequest) {
//火狐 , Safari 等瀏覽器
httpRequest = new XMLHttpRequest();
if (httpRequest.overrideMimeType)
httpRequest.overrideMimeType('text/xml' );
}//判斷是否支持Active控件對(duì)象
else if (window.ActiveXObject) {
//IE瀏覽器
try {
//IE5.0
httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
//IE5.5以上
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
}
}
//返回創(chuàng)建好的AJAX對(duì)象
return httpRequest;
}
(2)文本框內(nèi)容改變的事件在不同瀏覽器下的使用
文本框內(nèi)容改變的事件目前來說還沒有一個(gè)標(biāo)準(zhǔn)的版本。我們目前只關(guān)心IE與火狐好了,那么在IE和火狐下這兩個(gè)時(shí)間分別怎么表示呢?
IE: onpropertychange
FireFox: oninput
那么如何在頁面加載時(shí),根據(jù)瀏覽器給文本框附加對(duì)應(yīng)的change事件呢?
1.JS如何判斷瀏覽器版本
//IE瀏覽器
if (navigator.userAgent.indexOf("MSIE") >0)
{ }
//火狐瀏覽器
if (isFirefox = navigator.userAgent.indexOf("Firefox") >0)
{}
2.根據(jù)瀏覽器版本給文本框附加對(duì)應(yīng)事件
function getOs() {
//判斷瀏覽器類型
if (navigator.userAgent.indexOf("MSIE") >0) {
//此時(shí)假設(shè)文本框id為'txtSearch'
//為文本框附加IE所支持的事件
document.getElementById('txtSearch').attachEvent("onpropertychange", search);
OsTyep ="MSIE";
} elseif (navigator.userAgent.indexOf("Firefox") >0) {
//此時(shí)假設(shè)文本框id為'txtSearch'
//為文本框附加火狐所支持的事件
document.getElementById('txtSearch').addEventListener("input", search, false);
OsTyep ="Firefox";
}
}
3.根據(jù)瀏覽器版本給文本框清除對(duì)應(yīng)事件
function ClearOS() {
if (navigator.userAgent.indexOf("MSIE") >0) {
//此時(shí)假設(shè)文本框id為'txtSearch'
//為文本框清除IE所支持的事件
document.getElementById( 'txtSearch').detachEvent("onpropertychange", search);
OsTyep ="MSIE";
} elseif (navigator.userAgent.indexOf("Firefox") >0) {
//此時(shí)假設(shè)文本框id為'txtSearch'
//為文本框清除火狐所支持的事件
document.getElementById( 'txtSearch').removeEventListener("input", search, false);
OsTyep ="Firefox";
}
}
2.客戶端的設(shè)計(jì)
(1)實(shí)現(xiàn)流程的分析
了解完以上知識(shí)點(diǎn)之后,我們來看一下實(shí)現(xiàn)搜索提示的一個(gè)整體流程:
- 首先客戶端通過文本框輸入事件捕獲輸入的關(guān)鍵字
- 在通過我們之前創(chuàng)建好的AJAX對(duì)象提交給服務(wù)器
- 服務(wù)器接受提交的關(guān)鍵字,進(jìn)行查詢將結(jié)果集返回給客戶端進(jìn)行顯示
(2)樣式的編寫
那么接下來我們來看一下樣式,其中包括當(dāng)文本框鼠標(biāo)移動(dòng)上去給邊框加顏色與搜索結(jié)果行選中的樣式等,這里就不細(xì)說了,列舉出來供參考:
<style type="text/css" media="screen">
body
{
font:11px arial;
}
/*設(shè)置提示提示列表上的樣式表*/
.search_link
{
background-color:#FFFFFF;
cursor: pointer;
line-height:24px;
text-indent:6px;
}
/*設(shè)置當(dāng)鼠標(biāo)移動(dòng)到提示列表上的樣式表*/
.search_link_over
{
background-color:#E8F2FE;
cursor: pointer;
line-height:24px;
text-indent:6px;
}
/*設(shè)置顯示搜索提示div的樣式表*/
#search_div
{
position:absolute;
background-color:#FFFFFF;
text-align:left;
border:1px solid #000000;
border-top:0px;
display:none;
min-width:553px;
width:553px;
}
/*文本框樣式*/
.mainInput {
line-height: 26px;
height: 28px;
width: 550px;
font-size: 16px;
font-family: "微軟雅黑", "宋體", Candara;
font-weight: normal;
color: #666;
margin: auto;
border: none;
text-indent: 8px;
}
/*鼠標(biāo)放上文本框樣式*/
.mainInputOver {
width:552px;
height:30px;
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: #b7b7b7;
border-right-color: #d0d0d0;
border-bottom-color: #d0d0d0;
border-left-color: #d0d0d0;
}
/*鼠標(biāo)離開文本框樣式*/
.mainInputFocus {
width:552px;
height:30px;
border: 1px solid #41b5f2;
}
/*點(diǎn)擊文本框樣式*/
.myBorder
{
width:552px;
height:30px;
border-top: 1px solid #CCCCCC;
border-bottom: 1px solid #DDDDDD;
border-left: 1px solid #DDDDDD;
border-right: 1px solid #DDDDDD;
}
</style>
(3)aspx頁面與ajax_search.js文件的編寫
接下來就是一個(gè)比較重要的環(huán)節(jié)了,aspx頁面與ajax_search.js文件中包含了整體包括顯示與請(qǐng)求的方法例如:
1.頁面的實(shí)現(xiàn)
<body onload="getOs()" onkeydown="if(event.keyCode==13)return false;">
<form id="form1" runat="server">
<div>
<div class="myBorder" onmouseover="this.className='mainInputOver'" onmouseout="this.className='myBorder'" onclick="this.className='mainInputFocus'">
<input type="text" id="txtSearch" name="txtSearch" onblur="HiddenDiv()" alt="SearchCriteria" autocomplete="off" class="mainInput"/>
</div>
<!--該DIV作為現(xiàn)實(shí)搜索提示的結(jié)果-->
<div id="search_div" style="margin-top:0px"></div>
</div>
</form>
</body>
2.根據(jù)瀏覽器創(chuàng)建AJAX對(duì)象
var searchReq = createAjaxObj();
var OsTyep ='';
function getOs() {
//判斷瀏覽器類型
if (navigator.userAgent.indexOf("MSIE") >0) {
document.getElementById( 'txtSearch').attachEvent("onpropertychange", search);
OsTyep ="MSIE";
} elseif (navigator.userAgent.indexOf("Firefox") >0) {
document.getElementById( 'txtSearch').addEventListener("input", search, false);
OsTyep ="Firefox";
}
}
function ClearOS() {
if (navigator.userAgent.indexOf("MSIE") >0) {
document.getElementById( 'txtSearch').detachEvent("onpropertychange", search);
OsTyep ="MSIE";
} elseif (navigator.userAgent.indexOf("Firefox") >0) {
document.getElementById( 'txtSearch').removeEventListener("input", search, false);
OsTyep ="Firefox";
}
}
function createAjaxObj() {
var httpRequest =false;
//判斷是否包含XMLHttpRequest對(duì)象 PS:將來IE高也有可能繼承次對(duì)象
if (window.XMLHttpRequest) {
//火狐 , Safari 等瀏覽器
httpRequest =new XMLHttpRequest();
if (httpRequest.overrideMimeType)
httpRequest.overrideMimeType( 'text/xml');
//ie: onpropertychange
//ff: oninput
} //判斷是否支持Active控件對(duì)象
elseif (window.ActiveXObject) {
//IE瀏覽器
try {
//IE5.0
httpRequest =new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
//IE5.5以上
httpRequest =new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
}
}
//返回創(chuàng)建好的AJAX對(duì)象
return httpRequest;
}
3.創(chuàng)建請(qǐng)求與返回?cái)?shù)據(jù)的顯示
//異步請(qǐng)求服務(wù)器獲取搜索結(jié)果
function search() {
if (searchReq.readyState ==4|| searchReq.readyState ==0) {
//獲得文本框中的值
var valStr = escape(document.getElementById("txtSearch").value);
//建立連接
searchReq.open("GET", encodeURI('Search.ashx?search='+ valStr+'&fresh='+ Math.random()), true);
//當(dāng)請(qǐng)求狀態(tài)改變時(shí)調(diào)用 handleSearch方法
searchReq.onreadystatechange = handleSearch;
searchReq.send( null);
}
}
//返回結(jié)果處理方法
function handleSearch() {
if (searchReq.readyState ==4) {
//獲得搜索提示結(jié)果的元素DIV
var searchDIV = document.getElementById("search_div");
searchDIV.innerHTML ="";
//用^將返回的文本數(shù)據(jù)分割成數(shù)組
var resultStrArr = searchReq.responseText.split("^");
//循環(huán)構(gòu)建HTML代碼
for (var i =0; i < resultStrArr.length -1; i++) {
var htmlStr ='<div onmouseover="selectOverDiv(this,'+i+');" ';
htmlStr +='onmouseout="selectOutDiv(this,'+i+');" ';
htmlStr +='onclick="setSearch(this.innerHTML);" ';
htmlStr +='class="search_link " style="display:block;width:100%;" >'+ resultStrArr[i] +'</div>';
searchDIV.innerHTML += htmlStr;
}
ShowDiv();
x =-1;
}
}
4.將數(shù)據(jù)選中數(shù)據(jù)顯示文本框中
上邊代碼中在循環(huán)構(gòu)建HTML代碼時(shí),我們給構(gòu)建的DIV加入了三個(gè)事件分別是:
1 onmouseover="selectOverDiv(this,'+i+');"
2 onmouseout="selectOutDiv(this,'+i+');"
當(dāng)鼠標(biāo)放上去時(shí)調(diào)用selectOutDiv函數(shù)傳遞自己進(jìn)去
3 onclick="setSearch(this.innerHTML);"
當(dāng)鼠標(biāo)點(diǎn)擊DIV時(shí)調(diào)用setSearch函數(shù)傳入本身DIV中內(nèi)容
那么還是來看下這幾個(gè)方法的實(shí)現(xiàn)吧:
function selectOverDiv(div_value, i) {
div_value.className = "search_link_over";
var my_div = document.getElementById( "search_div").getElementsByTagName("div")
var the_num = my_div.length;
for (var k = 0; k < the_num; k++) {
selectOut(my_div[k]);
if (k == i) {
selectOver(my_div[k])
}
}
isCheckDiv = true ;
x = i;
}
function selectOutDiv(div_value,i) {
isCheckDiv = false;
div_value.className = "search_link";
x = i;
}
function setSearch(value) {
//清空文本框的內(nèi)容改變事件是因?yàn)槲覀兘o選中值復(fù)制時(shí) 該事件會(huì)觸發(fā)
//所以先清空次事件
ClearOS();
document.getElementById( "txtSearch").value = value;
//設(shè)置該屬性為false 在調(diào)用HiddenDiv函數(shù)會(huì)隱藏提示結(jié)果DIV
isCheckDiv = false;
HiddenDiv();
//在賦值完成后再次附加修改時(shí)間
getOs();
}
function ShowDiv() {
var content = document.getElementById( "txtSearch").value;
var divConten = document.getElementById( "search_div").innerHTML;
if (content != '' && divConten != '') {
document.getElementById( "search_div").style.display = "block"
} else {
isCheckDiv = false ;
HiddenDiv();
}
}
function HiddenDiv() {
if (isCheckDiv == false ) {
document.getElementById( "search_div").style.display = "none";
document.getElementById( "search_div").innerHTML = '';
}
}
5.增加鍵盤上下鍵選中提示數(shù)據(jù)與回車鍵選中數(shù)據(jù)到文本框
var index =-1; //表示當(dāng)前選中的行索引
function keyDown() {
var value = event.keyCode
//向上38,向下40,回車13
var the_key = event.keyCode
//判斷提示DIV是否是現(xiàn)實(shí)狀態(tài)
if (document.getElementById("search_div").style.display !="none") {
//獲取里面所用行
var my_div = document.getElementById("search_div").getElementsByTagName("div")
var the_num = my_div.length;
switch (the_key) {
case40: //向下
//判斷index是否已經(jīng)到最下面
if (index == the_num -1) {
index =0;
} else {
index ++;
}
//清楚所有選中
for (var i =0; i < the_num; i++) {
selectOut(my_div[i]);
}
//根據(jù)index選中對(duì)應(yīng)索引行
for (i =0; i < the_num; i++) {
if (i == index) {
selectOver(my_div[i])
}
}
break;
case38: //向上
//判斷index是否已經(jīng)到最上面
if (index ==0) {
index = the_num-1;
} else { index--; }
//清楚所有選中
for (var i =0; i < the_num; i++) {
selectOut(my_div[i]);
}
//根據(jù)index選中對(duì)應(yīng)索引行
for (i =0; i < the_num; i++) {
if (i == index) {
selectOver(my_div[i])
}
}
break;
case13: //回車
//將選中的內(nèi)容放入文本框中
if (my_div[index].innerHTML !=null) {
setSearch(my_div[index].innerHTML);
}
break;
}
}
}
document.onkeydown = keyDown;
3.服務(wù)器端的設(shè)計(jì)
(1)實(shí)現(xiàn)一個(gè)虛擬的數(shù)據(jù)源
前臺(tái)傳來關(guān)鍵字,后臺(tái)必須要有數(shù)據(jù)匹配,為了簡(jiǎn)單我就不建立數(shù)據(jù)庫了 我就模擬一個(gè)數(shù)據(jù)源好啦!
步驟:右鍵項(xiàng)目 --> 添加新項(xiàng)--> 選擇一般處理程序命名為:Search.ashx 編寫代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.CodeDom;
using System.Globalization;
using System.ComponentModel;
using System.Collections;
public class Search : IHttpHandler {
//定義一個(gè)數(shù)據(jù)源
public List <string> DataSource
{
get
{
List <string> list = new List<string>()
{
"我愛C#",
"我愛.NET",
"我愛微軟技術(shù)"
};
return list;
}
}
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
}
public bool IsReusable {
get {
return false;
}
}
}
(2)搜索數(shù)據(jù)源返回固定格式數(shù)據(jù)以字符串形式
緊接著我們要在ProcessReques方法中加入我們搜索數(shù)據(jù)源構(gòu)建返回相應(yīng)數(shù)據(jù)集,拼接結(jié)果字符串返回給客戶端。代碼如下:
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "text/plain";
//接受客戶端關(guān)鍵字并且解碼
string searchStr = HttpUtility.UrlDecode(context.Request.QueryString[ "search"].ToString(), System.Text.Encoding.UTF8);
//搜索數(shù)據(jù)源集合中匹配的關(guān)鍵字
var result = (from string n in DataSource
where n.Contains(searchStr)
select n).ToList <string>();
StringBuilder sb = new StringBuilder(100);
//將匹配關(guān)鍵字用符號(hào)^ 分割拼接成字符串
foreach (string str in result as List <string>)
{
sb.AppendFormat( "{0}^", str);
}
//返回客戶端
context.Response.Write(sb.ToString());
}
標(biāo)簽:
本站文章除注明轉(zhuǎn)載外,均為本站原創(chuàng)或翻譯。歡迎任何形式的轉(zhuǎn)載,但請(qǐng)務(wù)必注明出處、不得修改原文相關(guān)鏈接,如果存在內(nèi)容上的異議請(qǐng)郵件反饋至chenjj@fc6vip.cn
文章轉(zhuǎn)載自:博客園