利用PHP+JavaScript打造AJAX搜尋窗

來源:互聯網
上載者:User

  一、 引言

  Web世界中一項廣為使用的功能就是搜尋。隨著Web技術的日益發展,為了更好地滿足客戶的需求,常規搜尋引擎開始對更多的非常規方式"敞開了大門"。在這方面,Yahoo!率先提供出其Y!Q服務。這個新的服務能夠使你搜尋任何web頁面,前提是該頁面的作者必須包括在他們的web頁面中。是服務技術實現了把相關的搜尋結果呈現到讀者眼前,從而向讀者展示更多的資訊而不必離開他們的當前頁面。

  Yahoo!的Y!Q服務的確是一個偉大的想法,但是它的出現也受到了一些批評。原因何在?首先,它要求用戶端必須使用Yahoo!的JavaScript並且你必須添加一個<form/>元素,以便滿足Yahoo!的搜尋要求。對於許多網站作者來說,提供該服務需求付出太多的努力。並且,在所有這些條件滿足之後,搜尋結果將以Yahoo!風格展現,從而破壞了使用者網站的外觀感覺。

  幸運的是,Yahoo!並非唯一的提供"從你的網站提供搜尋結果"服務的搜尋引擎。MSN Search也提供一種類似服務,除了它能夠使web開發人員控制外觀感覺以外。這種能力來自於MSN Search提供它的搜尋結果的RSS版本,從而使得訂閱一個特定的搜尋或使用Ajax方法把該結果添加到你的頁面成為可能。

  儘管Google已經率先實現了這種新的"從你的網站進行搜尋"技術;但是,在本文成文之時,與Google相關的Google BlogSearch Beta也已經能夠以RSS或者Atom格式提供返回的結果。

  二、 伺服器端組件

  使用MSN Search執行搜尋時,你會看到一個桔黃色的XML映像出現在結果頁面的底部。點擊這個映像將會把你帶到一個新的頁面,並提供給你訂閱該搜尋的URL。

  這樣以來,你就可以編寫伺服器端代碼以檢索遠程饋送。對於本文中的搜尋窗,你將使用PHP檢索搜尋饋送。來自於伺服器應用程式請求資訊的URL看起來如下所示:

websearch.php?search=[SEARCHTERM]
  查詢字串只有一個變數:"search";因此,應用程式應該尋找此查詢項。在伺服器端,你需要建立一個頁面來"拉動"這個資料:

<?php
header("Content-Type: text/xml");
header("Cache-Control: no-cache");if ( isset($_GET["search"]) )
{
 $searchTerm = urlencode( stripslashes($_GET["search"]) );
 $url = "http://search.msn.com/results.aspx?q=$searchTerm&format=rss";
 $xml = file_get_contents($url);
 echo $xml;
}
?>
  前兩行設定要求的頭部以便瀏覽器能夠正確處理資料(XML形式,並且沒有對結果予以緩衝)。下一行代碼使用isset()函數來決定是否搜尋鍵存在於查詢字串中。

  為了把一個合適的請求發送到遠程主機,搜尋術語應該通過許多函數的"過濾"。首先,它被傳遞給stripslashes()函數。如果在PHP配置中啟動了"magic quotes"(預設情況下是支援的),那麼,到達PHP引擎的任何引號都會被使用一個斜杠(如,\"search query\")自動地脫掉。該stripslashes()函數負責刪除這些符號,僅留下"search query"。在刪除斜杠後,轉到urlencode()函數,由這個函數負責編碼字元以用於查詢字串。空格、引號、"&"等符號都被編碼。

  注意 如果搜尋術語不能通過這些函數的"過濾",那麼,MSN伺服器將返回一個代碼400-"Bad Request"。

  當為轉換搜尋術語準備好後,它被包括到URL中並儲存於$url變數中。最後,file_get_contents()函數負責開啟遠程檔案,讀取其內容並以一個字串形式把它返回到$xml變數中,然後使用echo命令把它列印到頁面中。

  三、 用戶端組件

  本文中的搜尋視窗(Widget)的用戶端代碼基於一個靜態對象msnWebSearch建立-它被定義為一個沒有任何屬性(現在)的對象:

var msnWebSearch ={};
  這個對象用於一個HTMLElement的onclick事件中執行搜尋:

<a href="#"
onclick='msnWebSearch.search(event,"Professional Ajax"); return false;'>
Professional Ajax
</a>
  這個msnWebSearch對象提供若干取得搜尋結果的方法,並負責繪製和放置包含這些資料的HTML。第一個方法是drawResultBox(),它負責繪製HTML。這個方法形成的HTML如下所示:

<divclass="ajaxWebSearchBox">
 <div class="ajaxWebSearchHeading">MSN Search Results
 <a class="ajaxWebSearchCloseLink" href="#">X</a>
</div>
<div class="ajaxWebSearchResults">
 <a class="ajaxWebSearchLink" target="_new" />
 <a class="ajaxWebSearchLink" target="_new" />
</div>
</div>
  該結果框分為兩部分:一個頭部和一個結果欄(見圖1)。頭部告訴使用者這個新的搜尋窗包含來自一個MSN搜尋的結果。它還包含一個"X"用於關閉該小視窗。其結果欄包含塊風格的連結,當點擊這些連結時將打一個新的視窗。


圖1.結果框分為兩部分:一個頭部和一個結果欄

  四、 繪製結果使用者介面

  產生這個HTML的代碼相當長,因為其中的元素都是使用DOM方法產生的。drawResultBox()方法接受一個參數(一個事件對象):

msnWebSearch.drawResultBox = function (e) {
 var divSearchBox= document.createElement("div");
 var divHeading = document.createElement("div");
 var divResultsPane = document.createElement("div");
 var aCloseLink = document.createElement("a");
  前面這些代碼經由createElement()方法建立HTML元素。在建立這些元素後,你就能夠開始賦予它們屬性。上面完成終結(封尾)的兩個元素分別是aCloseLink和divHeading:

aCloseLink.href = "#";
aCloseLink.className = "ajaxWebSearchCloseLink";
aCloseLink.onclick = this.close;
aCloseLink.appendChild(document.createTextNode("X"));
divHeading.className = "ajaxWebSearchHeading";
divHeading.appendChild(document.createTextNode("MSN Search Results"));
divHeading.appendChild(aCloseLink);
  前四行完成關閉結果框的連結。其中,方法close()成為連結的onclick事件的處理器。後面的幾行代碼負責使用文本和關閉連結填充頭部的<div/>。

  當這個結果框被繪製到頁面上時,還沒有接收到來自於一個伺服器應用程式的響應。為了向使用者展示已經發生了什麼,可以向使用者展示一個訊息提示資料正在載入中(這種方式更友好些)(見圖2)。為此,建立另一個元素並且把它添加到divResultsPane元素:

var divLoading = document.createElement("div");
divLoading.appendChild(document.createTextNode("Loading Search Feed"));

divResultsPane.className = "ajaxWebSearchResults";
divResultsPane.appendChild(divLoading);
  這個代碼建立載入訊息並且把它添加到divResultsPane,同時還把類名賦給divResultsPane。


圖2.向使用者提示資料正在載入中


  完成這些元素之後,剩下的就是把它們添加到divSearchBox元素中:

divSearchBox.className = "ajaxWebSearchBox";
divSearchBox.appendChild(divHeading);
divSearchBox.appendChild(divResultsPane);
document.body.appendChild(divSearchBox);
  這段代碼負責把divHeading和divResultsPane元素添加到搜尋窗,並且把搜尋窗添加到頁面。

  在drawResultBox()中的最後一步是確定新繪製的小框的位置並且把divSearchBox返回到它的調用者:

msnWebSearch.drawResultBox = function (e) {
 var divSearchBox= document.createElement("div");
 var divHeading = document.createElement("div");
 var divResultsPane = document.createElement("div");
 var aCloseLink = document.createElement("a");
 aCloseLink.href = "#";
 aCloseLink.className = "ajaxWebSearchCloseLink";
 aCloseLink.onclick = this.close;
 aCloseLink.appendChild(document.createTextNode("X"));
 divHeading.className = "ajaxWebSearchHeading";
 divHeading.appendChild(document.createTextNode("MSN Search Results"));
 divHeading.appendChild(aCloseLink);
 var divLoading = document.createElement("div");
 divLoading.appendChild(document.createTextNode("Loading Search Feed"));
 divResultsPane.className = "ajaxWebSearchResults";
 divResultsPane.appendChild(divLoading);
 divSearchBox.className = "ajaxWebSearchBox";
 divSearchBox.appendChild(divHeading);
 divSearchBox.appendChild(divResultsPane);
 document.body.appendChild(divSearchBox);
 this.position(e, divSearchBox);
 return divSearchBox;
};
  通過這種方式建立msnWebSearch對象後,必須把divSearchBox返回到它的調用者以便進行其它操作。你可以已經猜出,position()方法負責放置該搜尋方塊。它接受兩個參數:傳遞到drawResultBox()的事件對象和divSearchBox元素:

msnWebSearch.position = function (e, divSearchBox) {
 var x = e.clientX + document.documentElement.scrollLeft;
 var y = e.clientY + document.documentElement.scrollTop;
 divSearchBox.style.left = x + "px";
 divSearchBox.style.top = y + "px";
};
  前兩行代碼得到左邊和頂部位置,用於放置搜尋結果框。執行這個操作要求使用兩種資訊。首先是滑鼠的x和y座標(這些資訊被儲存在clientX和clientY屬性)。

  然而,這些座標還不足以正確定位結果框,因為clientX和clientY屬性返回相對於瀏覽器視窗客戶區的滑鼠位置,而不是頁面中的實際座標。考慮到這一點,我們可以使用文件項目的scrollLeft和scrollTop屬性。計算出最後的座標後,你能夠最後確定使用者點擊滑鼠的框中的位置。

  五、 顯示結果

  populateResults()方法負責使用搜尋結果填充結果欄。它接受兩個參數:包含該結果的元素和一個XParser對象(XParser是一個基於JavaScript的RSS讀取器,可從www.wdonline.com/javascript/xparser/自由下載):

msnWebSearch.populateResults = function(divResultsPane,oParser){
 var oFragment = document.createDocumentFragment();

 divResultsPane.removeChild(divResultsPane.firstChild);
  這個方法以編程方式並通過DOM方法產生<a/>元素;這樣以來,這些元素將被添加到一個在第一行建立的文檔片斷中。下一行刪除添加在drawResultBox()中的正載入的<div/>元素。

  下一步是建立這個連結:

for (var i = 0; i < oParser.items.length; i++) {
 var oItem = oParser.items[i];

 var aResultLink = document.createElement("a");
 aResultLink.href = oItem.link.value;
 aResultLink.className = "ajaxWebSearchLink";
 aResultLink.target = "_new";
 aResultLink.appendChild(document.createTextNode(oItem.title.value));

 oFragment.appendChild(aResultLink);
}
  這段代碼遍曆回饋的各個項,並且由該資料產生連結並把<a/>元素添加到文檔片斷最後。

  當退出迴圈時,該文檔片斷被添加到divResultsPane以顯示搜尋結果:

divResultsPane.appendChild(oFragment);
  六、 關閉結果框

  為了關閉搜尋結果框,msnWebSearch對象提供了close()方法。close()方法負責處理該連結的onclick事件(關閉該小框):

msnWebSearch.close = function () {
 var divSearchBox = this.parentNode.parentNode;
 document.body.removeChild(divSearchBox);

 return false;
};
  該搜尋方塊其實並沒有關閉;事實上,它被從該文檔中刪除了。為此,需要檢索divSearchBox元素。第一行程式碼完成這一任務-通過檢索這個元素的父結點的父結點實現。因為close()負責處理onclick事件,所以this引用這一連結。下一行從文檔中刪除divSearchBox元素。最後一行,返回false,從而強迫瀏覽器不要沿用一個連結的預設行為(轉到在href屬性中標註的位置)。

  七、 構建搜尋介面

  msnWebSearch對象的最後一個方法是search(),它提供執行一個搜尋的介面。你可以使用一個元素的onclick事件來調用search()。它接受兩個方法:一個事件對象和搜尋術語:

msnWebSearch.search = function (e,sSearchTerm) {
 var divSearchBox = this.drawResultBox(e);
 var url = encodeURI("websearch.php?search=" + sSearchTerm);
 var oParser = new XParser(url);
 oParser.onload = function () {
  msnWebSearch.populateResults(divSearchBox.childNodes[1],oParser);
 };
};
  第一行調用drawResultBox()方法並且把事件e傳遞給它。下一行編碼該URL以實現合適的轉換。這個URL被傳遞給XParser構造器以建立一個新的分析器。當搜尋回饋完成載入並使用結果填充搜尋方塊時,該分析器的onload事件處理器調用populateResult()方法。
當然,構建這個搜尋方塊的一個理由是,使其更適合於你自己的網站的外觀。

  八、 定製Web搜尋方塊

  藉助於CSS,你可以容易地為你的現有網站定製搜尋方塊,並且使你以後的任何重新設計都變得非常容易。

  首先要討論的CSS類是ajaxWebSearchBox(該類實現搜尋方塊)。因為搜尋方塊要確定位置,所以它必須要有一個絕對位置:

.ajaxWebSearchBox
{
 position: absolute;
 background-color: #0d1e4a;
 width: 500px;
 padding: 1px;
}
  在此,絕對位置是唯一的要求。所有的其它屬性都是根據你的口味可選的。在這個樣本中,該框有一個微藍色的背景,一個500像素的寬度,以及在四邊上各有1個像素的填充。這個填充導致圍繞該框的內容的是1個像素寬的邊界。

  下一個類是ajaxWebSearchHeading,它包含該框的頭部文本和關閉連結。為了把關閉連結放在右上方,它使用絕對位置。因為這個原因,它要求ajaxWebSearchHeading使用一個相對位置:

.ajaxWebSearchHeading
{
 position: relative;
 background-color: #1162cc;
 font: bold 14px tahoma;
 height: 21px;
 color: white;
 padding: 3px 0px 0px 2px;
}
  在此,唯一要求的屬性也是position屬性。其它的屬性有助於給出該元素一個好看的外觀。其背景顏色是淺藍色,而文本部分是白色,14像素高且是Tahoma字型。該元素的高度是21個像素並且在頂部和左邊都填充以邊界。

  如前面所述,該關閉連結的位置是絕對的:

a.ajaxWebSearchCloseLink
{
 position: absolute;
 right: 5px;
 top: 3px;
 text-decoration: none;
 color: white;
}
a:hover.ajaxWebSearchCloseLink
{
 color: red;
}
  該元素被放置在距右邊5個像素,距頂部3個像素的位置(該元素被放在右上方)。這個連結沒有任何文本修飾並且顏色呈白色。當使用者的滑鼠停在該連結上時,文本顏色變紅。

  注意,這裡沒有使用訪問過的或活動的"假"類。這是因為該視窗總是忽略這個連結的href屬性(它已經在它的事件處理器中返回了false)。因此,該連結從來不會真正處於活動或被訪問狀態。

  然後,ajaxWebSearchResults類使結果欄的風格如下:

.ajaxWebSearchResults
{
 background-color: #d3e5fa;
 padding: 5px;
}
  這個元素不要求使用CSS屬性。現有屬性僅用於定義結果欄並且使它比較容易讀取。背景顏色是一個淺藍色並且圍繞邊緣有5個像素的填充。當然,你能夠定製載入訊息的風格:

.ajaxWebSearchResults div
{
 text-align: center;
 font: bold 14px tahoma;
 color:#0a246a;
}
  這個元素沒有一個類名,但是你仍然能夠通過使用前面的樣本中展示的parent child標誌控制它的風格。這個樣本把文本放置在<div/>元素的中央,並且給它一個加粗藍色的字型,且有14個像素高。

  最後一個你需要風格化的元素是結果連結。這些連結有一個類名叫ajaxWebSearchLink:

a.ajaxWebSearchLink
{
 font: 12px tahoma;
 padding: 2px;
 display: block;
 color: #0a246a;
}
a:hover.ajaxWebSearchLink
{
 color: white;
 background-color: #316ac5;
}
a:visited.ajaxWebSearchLink
{
 color: purple;
}
  唯一要求的屬性是display屬性(被設定為block)。這使每一個連結都能夠在它自己的行上顯示。填充空白部分大約有兩個像素寬,使各個連結之間分開一些,從而使它們更易於讀取。字型名為Tahoma並且有12像素高。它們的顏色是暗藍色,與ajaxWebSearchResults的淺藍色背景形成對照。

  當使用者在這些連結上移動滑鼠時,背景顏色被設定為藍色,而文本顏色改變為白色。

  在前面的代碼的最後一條規則中訪問過的"假"類被設定。這是為了給使用者提供使用者介面暗示-它們已經被使用過。通過把訪問過的"假"類設定為顯示一種紫色,使用者就可以知道它們已經訪問過那個連結,從而節省他們的時間-不必再訪問一個他們可能不想看的頁面。

  現在,讓我們來看一下如何?搜尋方塊。

  九、 實現Web搜尋搜尋方塊

  實現這個搜尋方塊是很簡單的。首先,你必須把websearch.php檔案上傳到你的web伺服器(當然,必須安裝PHP)。然後,你需要一個HTML文檔來引用所有的組件。msnWebSearch對象依賴於XParser類,這個類又依賴於zXml庫(可從www.nczonline.net/downloads/下載)。你必須引用下面這些檔案:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax WebSearch</title>
<link rel="stylesheet" type="text/css" href="css/websearch.css" />
<script type="text/javascript" src="js/zxml.js"></script>
<script type="text/javascript" src="js/xparser.js"></script>
<script type="text/javascript" src="js/websearch.js"></script>
</head><body>
</body>
</html>
  為了執行搜尋,應該把msnWebSearch.search()方法設定為該元素的onclick處理器:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xml:lang="en" lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Ajax WebSearch</title>
<link rel="stylesheet" type="text/css" href="css/websearch.css" />
<script type="text/javascript" src="js/zxml.js"></script>
<script type="text/javascript" src="js/xparser.js"></script>
<script type="text/javascript" src="js/websearch.js"></script>
</head><body>
<a href="#" onclick='msnWebSearch.search(event,"\"Professional Ajax\"");
return false;'>Search for "Professional Ajax"</a>
<br /><br /><br /><br />
<a href="#" onclick='msnWebSearch.search(event,"Professional Ajax");
return false;'>Search for Professional Ajax</a>
</body>
</html>
  第一個新的連結執行一個針對準確片語"Professional Ajax"的搜尋,而第二個連結將搜尋這其中的各個單詞。還要注意,在onclick事件中返回的是false-這強迫瀏覽器忽略掉href屬性。點擊這些連結將在游標位置繪製搜尋方塊,並且就在此處顯示你的搜尋結果。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.