iframe创建智能表单
16.5 使用iframe创建智能表单
使用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()函数,在本例中对该函数也做了少量的修改。现在,该函数将接收两个参数:第一个参数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—— 本质上我们可以采用任何一种能够以文本格式返回数据的服务器端编程技术。