使用xmlhttprequest對象實現ajax功能的好處在于xmlhttprequest對象使用簡單。只需創建一個xmlhttprequest對象,然后發送請求并等待服務器的響應。不幸的是,使用javascript對象具有一個弊端,即瀏覽器并不會在其歷史記錄中保存由xmlhttprequest對象發起的http請求。因此,實際上xmlhttprequest對象使得瀏覽器的back按鈕功能失效了。
相關文章:xmlhttprequest創建智能表單
實現智能表單的第二個解決方案就是使用一項早期的ajax技術,即使用隱藏框架(frame)或隱藏內嵌框架(iframe)來實現客戶端/服務器之間的通信。為了正確地實現ajax功能,必須使用兩個框架頁,其中,一個框架頁必須是隱藏的,另一個框架頁則必須是可見的。
注意:
當使用iframe來實現ajax技術時,包含iframe的頁面必須是可見的。
隱藏框架技術實現ajax通常由4個過程組成。第一步是由用戶的某種行為引發了一個對隱藏框架的請求。這包括用戶單擊了在可見框架頁中的超鏈接,或者由用戶的其他交互行為所引發。通常情況下,對隱藏框架頁的請求僅僅是將隱藏框架頁重定向到一個服務器上指定的服務端程序。對隱藏框架頁的重定向將自動觸發第二個過程:即向服務器發送請求。
在服務器程序完成了對請求的處理之后,將發生第三個過程:即服務器將響應發送回隱藏框架頁。服務器端的響應是一個web頁面,該頁面將被發送給隱藏框架。當來自服務器的響應被完全接收后,隱藏框架中的web頁面將發起與可見框架頁的聯系,并告知可見框架,服務器的響應已經成功。這就是第四個過程,該過程通常在隱藏框架的window.onload事件處理器中完成。
這一小節中的例子將基于前一小節中所創建的程序。但不同的是,我們將通過隱藏框架來實現瀏覽器與服務器之間的通信。在編寫代碼之前,我們先來討論一下從服務器將返回什么樣的數據。
注意:
下面的例子并不適用于safari瀏覽器,safari瀏覽器并不會在其歷史記錄中保存iframe內嵌框架的瀏覽歷史。
當我們使用xmlhttprequest對象從服務器獲取數據時,在服務器的響應中僅需要包含很少的關鍵字。盡管所包含的關鍵字可能有所不同,但是服務器的響應必須由以下兩部分組成:
● 第一是必須包含響應的數據,而且該數據必須是html格式。
● 第二是當iframe接收到html形式的響應時,必須有一個機制通知父框架頁中的文檔。
記住這兩個組成部分之后,下面我們就來構造服務器響應的html頁面。服務器的響應將是一個html文件,該html文件具有如下的結構:
<html>
<head>
<title>returned data</title>
</head>
<body>
<script type="text/javascript">
//more code here
</script>
</body>
</html>
上面的html頁面非常簡單,在頁面文檔中僅包含一個<script/>元素。位于腳本塊中的javascript代碼將由服務器端的php程序生成,在這段腳本中,將調用位于可見框架頁中的函數checkusername_callback()或者checkemail_callback(),并將available或者not available作為參數傳遞給相應的函數。例如,下面的html代碼就是一個由服務器端php程序生成的有效的響應頁面。
<html>
<head>
<title>returned data</title>
</head>
<body>
<script type="text/javascript">
top.checkusername_callback("available", "some_username");
</script>
</body>
</html>
在上面有效響應頁面的代碼中,假定所檢查的用戶名是有效的。因此,在該響應頁面的腳本塊中,調用了父窗口中的checkusername_callback()函數,并將字符串available作為參數傳遞給checkusername_callback()函數。對于檢查用戶名或e-mail的請求,相應的響應頁面將被發送回客戶端。之所以要把所查找的用戶名或e-mail通過響應頁面發送回客戶端,是為了當用戶單擊瀏覽器的back或forward按鈕時,客戶端程序能夠正確地顯示輸入的用戶名或e-mail。采用以上形式的服務器響應頁面,可以使前例中的大部分代碼保持不變,直接用在本例中。
使用iframe實現的智能表單與前面使用xmlhttprequest對象的例子非常類似。而且相應的代碼也只需進行少量的改動。打開文本編輯器,并輸入下列代碼:
<html>
<head>
<title>form field validation</title>
<style type="text/css">
.fieldname
{
text-align: right;
}
.submit
{
text-align: right;
}
#hiddenframe
{
display: none;
}
</style>
<script type="text/javascript">
function checkusername()
{
var uservalue = document.getelementbyid("username").value;
if (uservalue == "")
{
alert("please enter a user name to check!");
return;
}
var url = "iframe_formvalidator.php?username=" + uservalue;
frames["hiddenframe"].location = url;
}
function checkusername_callback(data, uservalue)
{
if (data == "available")
{
alert("the username " + uservalue + " is available!");
}
else
{
alert("we’re sorry, but " + uservalue + " is not available.");
}
}
function checkemail()
{
var emailvalue = document.getelementbyid("email").value;
if (emailvalue == "")
{
alert("please enter an email address to check!");
return;
}
var url = "iframe_formvalidator.php?email=" + emailvalue;
frames["hiddenframe"].location = url;
}
function checkemail_callback(data, emailvalue)
{
if (data == "available")
{
alert("the email " + emailvalue + " is currently not in use!");
}
else
{
alert("we’re sorry, but " + emailvalue+ " is in use by another user.");
}
}
</script>
</head>
<body>
<form>
<table>
<tr>
<td class="fieldname">
username:
</td>
<td>
<input type="text" id="username" />
</td>
<td>
<a href="javascript: checkusername()">check availability</a>
</td>
</tr>
<tr>
<td class="fieldname">
email:
</td>
<td>
<input type="text" id="email" />
</td>
<td>
<a href="javascript: checkemail()">check availability</a>
</td>
</tr>
<tr>
<td class="fieldname">
password:
</td>
<td>
<input type="text" id="password" />
</td>
<td />
</tr>
<tr>
<td class="fieldname">
verify password:
</td>
<td>
<input type="text" id="password2" />
</td>
<td />
</tr>
<tr>
<td colspan="2" class="submit">
<input type="submit" value="submit" />
</td>
<td />
</tr>
</table>
</form>
<iframe src="about:blank" id="hiddenframe" name="hiddenframe" />
</body>
</html>
將上面的代碼保存為validate_iframe_form.htm頁面,并將該頁面保存在web服務器的根目錄之下。從本書的代碼下載中查找并下載iframe_formvalidator.php文件,并將該文件也保存在相同的目錄中。
打開瀏覽器(非safari的瀏覽器)并加載http://localhost/validate_iframe_form.htm頁面。你將看到一個如圖16-7所示的頁面。
輸入三個用戶名和e-mail地址進行檢查。在關閉了最后一個alert對話框之后,單擊瀏覽器的back按鈕幾次。你將看到你所輸入的幾個用戶名或e-mail地址的信息將按倒序出現。文本框中的信息并沒有發生改變,但是彈出的alert對話框將顯示你所輸入的用戶名和e-mail地址。你也可以單擊瀏覽器的forward按鈕進行測試。

圖 16-7
代碼解說
在上面的html代碼中,除了在表單的結束標記<form/>之后添加了一個<iframe/>元素之外,其他的html元素都保持不變。所添加的<iframe/>元素如下所示:
<iframe src="about:blank" id="hiddenframe" name="hiddenframe" />
該嵌入框架被初始化為一個空白的html頁面,其name屬性和id屬性都被設置為hiddenframe。在后面的代碼中,我們將通過name屬性,從bom對象的frames集合中引用這個嵌入框架。接下來,設置該嵌入框架的css樣式。
#hiddenframe
{
display: none;
}
該元素規則僅包含了一個樣式聲明,該樣式聲明將<iframe/>元素隱藏起來。
注意:
通過css的方式來隱藏<iframe/>元素,可以在需要調試服務器端程序時將<iframe/>元素很方便地顯示出來。
下面是頁面中的javascript代碼。
function checkusername()
{
var uservalue = document.getelementbyid("username").value;
if (uservalue == "")
{
alert("please enter a user name to check!");
return;
}
var url = "iframe_formvalidator.php?username=" + uservalue;
frames["hiddenframe"].location = url;
}
對于checkusername()函數,僅僅做了一點小小的修改:該函數將使用iframe而不是使用xmlhttprequest對象來向目標服務器發起請求。在該函數中,首先獲取了username文本框的值。并對用戶是否在文本框中輸入了數據進行檢查。如果文本框為空,則彈出一個對話框以告訴用戶需要在username文本框中輸入用戶名。如果username文本框不為空,則構造一個向目標服務器發送請求的查詢字符串,并將該請求字符串的url保存在變量url中。最后一步使用frames集合來引用該iframe,并將其location屬性設置為url,以在iframe中加載由url指定的服務器端頁面。
頁面中的第二個函數是checkusername_callback()函數,在本例中對該函數也做了少量的修改?,F在,該函數將接收兩個參數:第一個參數data的值將是available或者not available;第二個參數uservalue的值就是在發起請求的查詢字符串中發送給服務器的用戶名。checkusername_callback()函數的代碼如下所示:
function checkusername_callback(data, uservalue)
{
if (data == "available")
{
alert("the username " + uservalue + " is available!");
}
else
{
alert("we’re sorry, but " + uservalue + " is not available.");
}
}
在checkusername_callback()函數中,首先檢查了從服務器返回的數據,即檢查data的值是否為available。如果是,則表示所申請的用戶名有效,并彈出一個對話框告訴用戶所申請的用戶名可用。否則,將彈出一個對話框,告訴用戶所申請的用戶名無效。
用于檢查e-mail地址的兩個函數與之非常類似。下面就是用于檢查e-mail地址是否有效的兩個函數:checkemail()函數和checkemail_callback()函數。
function checkemail()
{
var emailvalue = document.getelementbyid("email").value;
if (emailvalue == "")
{
alert("please enter an email address to check!");
return;
}
var url = "iframe_formvalidator.php?email=" + emailvalue;
frames["hiddenframe"].location = url;
}
function checkemail_callback(data, emailvalue)
{
if (data == "available")
{
alert("the email " + emailvalue + " is currently not in use!");
}
else
{
alert("we’re sorry, but " + emailvalue + " is in use by another user.");
}
}
checkemail()函數的處理過程與checkusername()函數類似。該函數首先獲取了email文本框中的值,并檢查是否為空。如果不為空,則使用該值構造一個發送請求的查詢字符串,并在iframe中加載該url指定的服務器頁面。
對checkemail_callback()函數所做修改與對checkusername_callback()函數所做的修改類似。同樣,該函數將接收兩個參數,根據從服務器返回的信息檢查用戶輸入的e-mail是否有效,并將相應的信息顯示給用戶。
上面這兩個例子都是比較簡單的,這兩個例子主要用于演示ajax技術是如何工作的。我們還可以使用其他的技術方案來實現智能表單(在一些技術方案中并不需要單擊超鏈接),其中一些技術方案易于實現,就像本章中的方案一樣。但一些技術方案則可能比較復雜。
實際上,ajax技術的本質就是:通過某種方式實現客戶端/服務器的通信,而無須刷新整個頁面。實現ajax技術的關鍵就是客戶端和服務器的程序。在上面的兩個例子中,我們可以看到,接收請求的服務器端程序需要處理請求的數據,并將處理結果返回給客戶端。顯然,我們需要采用某種服務器端的技術來執行所請求的功能,這樣才能把ajax技術的優勢發揮到極致。我們可以采用任何一種服務器端的編程技術,如php、asp或 .net、coldfusion、perl—— 本質上我們可以采用任何一種能夠以文本格式返回數據的服務器端編程技術。
新聞熱點
疑難解答