
用于 PHP Web 应用程序的 Ajax 简介
本文档介绍了 Ajax,并展示了 NetBeans IDE 中的一些功能,这些功能使您在使用 Ajax 相关技术编程时更加快捷高效。在学习 Ajax 初级功能时,您将生成一个用于自动完成文本字段的简单应用程序。此处的内容改编自 Greg Murray 的文章,样例应用程序取自将 Ajax 与 Java 技术一起使用。
Ajax 代表异步 JavaScript 和 XML (Asynchronous JavaScript and XML)。在本质上,Ajax 是一种 Web 应用程序用来处理用户与 Web 页间交互的有效方法,它不需要在每次用户交互时都进行页面刷新或重新装入完整页面。这样就能在使用浏览器时提供丰富的行为(与桌面应用程序或基于插件的 Web 应用程序的行为类似)。Ajax 交互在后台异步处理。同时,用户可以继续使用页面。Ajax 交互由 JavaScript 代码启动。Ajax 交互完成后,JavaScript 会更新页面的 HTML 源代码。这些更改会立即进行,不需要刷新页面。Ajax 交互可用于执行一些操作,如使用服务器端逻辑验证表单条目(当用户输入表单条目时)、检索服务器中的详细数据、动态更新页面上的数据,以及从页面提交部分表单。
NetBeans IDE 为 Ajax 开发提供了强大的支持,其中包括 JavaScript 和 CSS 编辑器、一个全新的 PHP 编辑器、一个 JavaScript 调试器(基于 Firefox 的 Firebug 插件),一个用于检查 HTTP 消息的客户端监视器、适用您所选服务器端脚本语言(例如,JSP、PHP、Ruby、Groovy)的现成 Ajax 的环境、对 MySQL 和 Java DB 的快捷支持,以及对 Web 框架和第三方 JavaScript 工具包的广泛集成支持。
目录
本页上的内容适用 NetBeans IDE 6.5
要学习本教程,您需要具备以下软件和资源。
注意:
- PHP 开发环境通常是使用 *AMP 包进行配置的,具体取决于您的操作系统。该环境包括 PHP 引擎和 Apache Web 服务器。有关配置环境的说明,请参见 PHP 学习资源。
- 本教程假设您已经具备它所使用的各种技术(即 HTML、CSS、JavaScript 和 PHP)的应用知识。它尝试以代码的形式提供功能的概述,但不解释每行代码的含义。
- 如果需要将项目与工作解决方案进行比较,可以下载样例应用程序。
应用程序概述
设想一个用户可以在其中搜索作曲家信息的 Web 页。该页面包含一个字段,用户可以在其中输入作曲家的名字。在示例应用程序中,输入字段具有自动完成功能。换句话说,用户可以键入作曲家的部分名字,然后 Web 应用程序即可以列出其名字或姓氏以所输入字符开头的所有作曲家,尝试完成整个名字。自动完成功能使用户不必记住作曲家的完整名字,并且可以更加直观和直接的搜索热门信息。
在搜索字段中实现自动完成功能可以使用 Ajax 来完成。Ajax 的工作原理是使用 XMLHttpRequest 对象在客户端和服务器之间异步传递请求和响应。下图说明了客户端和服务器之间进行通信的过程流。
该图中的过程流可以按以下步骤进行解释:
- 用户触发一个事件,例如,在键入名字时释放一个按键。这会引发调用初始化
XMLHttpRequest 对象的 JavaScript 函数。
XMLHttpRequest 对象将使用一个请求参数进行配置,该参数将包含触发该事件的组件 ID 以及用户所输入的任何值。然后,XMLHttpRequest 对象将向 Web 服务器发出异步请求。
- 在 Web 服务器上,诸如 servlet 或侦听器之类的对象会处理该请求。从数据存储检索数据,并且准备一个响应,其中包含 XML 文档形式的数据。
- 最后,
XMLHttpRequest 对象使用回调函数接收 XML 数据并对其进行处理,然后更新 HTML DOM(Document Object Model, 文档对象模型)以显示包含新数据的页面。
本教程说明了如何根据上图所示的过程流构建自动完成方案。首先,为生成 XMLHttpRequest 对象所需的表示和功能创建客户端文件。然后,通过使用基于 PHP 的技术创建数据存储和业务逻辑来设置服务器端。最后,返回客户端,并实现 callback() 和其他 JavaScript 功能以更新 HTML DOM。
客户端编程:第 1 部分
首先在 IDE 中新建一个新的 Web 应用程序项目。IDE 中包含多种项目类型的内置模板。
- 选择“文件”>“新建项目”。在“类别”下,选择 "PHP"。在“项目”下,选择“PHP 应用程序”,然后单击“下一步”。
- 在“名称和位置”面板中,输入 MyAjaxApp 作为项目名称。使用“源文件夹”字段可以在计算机上指定项目的位置。保留选项的缺省设置,然后单击“下一步”。

- 在“运行配置”面板中,指定您要部署应用程序的方式。如果您已通过配置 *AMP 包设置了 PHP 开发环境,则应该从下拉列表中选择“本地 Web 站点”,并指定项目的 URL(将显示在浏览器中)。
- 选中“将源文件夹中的文件复制到其他位置”选项。然后,在“复制到文件夹”字段中,键入到服务器上部署位置的路径。(在 Apache 上,部署位置是缺省的
htdocs 目录。)

- 单击“完成”。IDE 会在您的文件系统中创建项目文件夹,项目将在 IDE 中打开。
注意:如果您在向导中指定正确的路径时遇到困难,请参见设置 PHP 项目查看详细说明。PHP 学习资源可以提供有关配置环境的更多信息。
将生成缺省的 index.php 入口页并在 IDE 的编辑器中打开。您的项目也会显示在“项目”窗口中。
在开始编码前,请立即尝试运行该应用程序以确保正确设置了 IDE、您的服务器和浏览器之间的配置。
- 在 IDE 的编辑器中,向索引页中添加一个
echo 语句:
<?php // put your code here echo "<h2>Hello World!</h2>"; ?>
- 在“项目”窗口中,右键单击项目节点,然后选择“运行”。IDE 会打开您的缺省浏览器,并显示您刚在
index.php 中创建的 Hello World 消息。
使用 HTML 编辑器
既然您确定已正确设置了您的环境,请首先将您的索引页转换成用户将查看的自动完成界面。
使用 IDE 的一个好处是:您所使用的编辑器通常可以为您提供代码完成功能,如果在编写代码时学会应用此功能,可以快速提高效率。一般来说,IDE 编辑器会适应您所使用的技术,因此,如果您正在处理 HTML 页,按下代码完成组合键(Ctrl-空格键)会产生有关 HTML 标记和属性的建议。下面您还将了解到,IDE 编辑器也适用其他技术(如 CSS 和 JavaScript)。
您可以使用的第二个功能是 IDE 的组件面板。组件面板为您编写代码所采用的技术中的常用元素提供了易于使用的模板。您只需单击某一项,然后将其拖动到源代码编辑器所打开的文件中的某个位置。
您可以查看大图标(如此处显示),方法是右键单击组件面板,然后选择“显示大图标”。
- 将
<title> 标记中的内容替换为:Auto-Completion using AJAX。此外,将 <h2> 标记替换为 <h1> 标记,然后键入您在 <title> 标记中所键入的文本。索引页不需要服务器端的脚本代码,因此您可以安全地删除 PHP 标记和先前添加的 echo 语句。现在,索引页应该如下显示。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Auto-Completion using AJAX</title> </head> <body> <h1>Auto-Completion using AJAX</h1> </body> </html>
- 添加一些说明性文本以介绍文本字段的用途。您可以复制以下文本并将其粘贴在
<h1> 标记下方的某一位置:
<p>This example shows how you can do real time auto-completion using Asynchronous JavaScript and XML (Ajax) interactions.</p>
<p>In the form below enter a name. Possible names that will be completed are displayed below the form. For example, try typing in "Bach," "Mozart," or "Stravinsky," then click on one of the selections to see composer details.</p>
- 向该页面中添加一个 HTML 表单。可以利用 IDE 组件面板中列出的元素执行此操作。如果组件面板没有打开,请从主菜单中选择“窗口”>“组件面板”。然后,在“HTML 表单”下,单击某个表单元素,并将其拖动到该页面中您刚添加的
<p> 标记下的某一位置。“插入表单”对话框即打开。指定以下内容:
- 操作:autocomplete
- 方法:GET
- 名称:autofillform
单击“确定”。HTML <form> 标记已插入到包含您所指定的属性的页面中。(GET 在缺省情况下应用,因此没有进行显式声明。)
- 向该页面添加一个 HTML 表格。在组件面板中的 "HTML" 类别下,单击某个表格元素,并将其拖动到
<form> 标记之间的位置。“插入表格”对话框即打开。指定以下内容:

- 在源代码编辑器中单击鼠标右键,然后选择“格式”。此操作将对代码进行整理。现在,您的表单应该如下显示:
<form name="autofillform" action="autocomplete"> <table border="0" cellpadding="5"> <thead> <tr> <th></th> <th></th> </tr> </thead> <tbody> <tr> <td></td> <td></td> </tr> <tr> <td></td> <td></td> </tr> </tbody> </table> </form>
- 将以下文本键入到此表格第一行的第一列中(更改的内容以粗体显示):
<td><strong>Composer Name:</strong></td>
- 在第一行的第二列中,手动键入以下代码(而不从组件面板中拖动一个文本输入字段)。
<input type="text" size="40" id="complete-field" onkeyup="doCompletion();">
在键入时,请尝试使用 IDE 内置的代码完成支持。例如,键入 <i,然后按 Ctrl-空格键。建议的选项列表会显示在光标下方,并且选中元素的说明会显示在上方的框中。事实上,在源代码编辑器中编写代码时,可以随时按 Ctrl-空格键调出可能的选项。而且,如果只有一个可用的选项,按 Ctrl-空格键将自动完成元素名称。

您在上文中键入的 onkeyup 属性指向名为 doCompletion() 的 JavaScript 函数。每次在表单文本字段中按下一个键时,此函数都会被调用,并映射到以上 Ajax 流程图中所描述的 JavaScript 调用。
使用 JavaScript 编辑器
IDE 的新 JavaScript 编辑器提供了许多高级编辑功能,如智能代码完成、语义突出显示、即时重命名、重构功能以及许多其他功能。请观看 NetBeans JavaScript 编辑器截屏视频以了解快速演示并参见 http://wiki.netbeans.org/JavaScript 获取详细规范。
当您使用其他技术(即 HTML、RHTML、JSP、PHP)在 .js 文件以及 <script> 标记中编码时,将自动提供 JavaScript 代码完成功能。当使用 JavaScript 编辑器时,IDE 会为您提供浏览器兼容性信息,具体取决于您在“JavaScript 选项”面板中指定的浏览器类型和版本。打开“JavaScript 选项”面板,方法是先选择“工具”>“选项”(在 Mac 上为 "NetBeans" >“首选项”),然后选择“其他”> "JavaScript"。
IDE 对 Firefox、Internet Explorer、Safari 和 Opera 提供了快捷支持。在“JavaScript 选项”面板中,您还可以指定代码完成功能适用的 JavaScript 引擎版本。
将 JavaScript 文件添加到此应用程序,然后开始实现 doCompletion()。
- 在“项目”窗口中,右键单击项目节点并选择“新建”>“JavaScript 文件”。(如果“JavaScript 文件”未列出,请选择“其他”。然后从“新建文件”向导的 "Web" 类别中选择“JavaScript 文件”。)
- 将文件命名为
javascript,然后单击“完成”。新的 JavaScript 文件会显示在“项目”窗口中,并在编辑器中打开。
- 将以下代码键入
javascript.js。
var req; var isIE;
function init() { completeField = document.getElementById("complete-field"); }
function doCompletion() { var url = "autocomplete.php?action=complete&id=" + escape(completeField.value); req = initRequest(url); req.open("GET", url, true); req.onreadystatechange = callback; req.send(null); }
function initRequest(url) { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { isIE = true; return new ActiveXObject("Microsoft.XMLHTTP"); } }
- 切换回
index.php,然后在 <head> 标记之间添加对 JavaScript 文件的引用。
<script type="text/javascript" src="javascript.js"></script>
您可以按 Ctrl-Tab 组合键在编辑器中打开的页面之间快速切换。
- 在开始标记
<body> 中,插入对 init() 的调用。
<body onload="init()">
这可以确保每次装入页面时,都会调用 init()。
doCompletion() 的作用是:
- 创建一个 URL,其中包含可由服务器端使用的数据,
- 初始化
XMLHttpRequest 对象,并
- 提示
XMLHttpRequest 对象向服务器发送一个异步请求。
XMLHttpRequest 对象是 Ajax 的核心,并已经成为通过 HTTP 异步传递 XML 数据的实际标准。异步交互意味着在发送请求之后浏览器可以继续处理页面中的事件。数据在后台进行传递,并且可以自动装入到页面中,无需进行页面刷新。
请注意,XMLHttpRequest 对象实际上是由 initRequest()(由 doCompletion() 调用)创建的。此函数用于检查浏览器是否可以识别 XMLHttpRequest;如果可以,即创建 XMLHttpRequest 对象。否则,它将对 ActiveXObject(相当于 Internet Explorer 的 XMLHttpRequest)进行检查,并创建 ActiveXObject(如果被识别)。
当您创建 XMLHttpRequest 对象时会指定三个参数:URL、HTTP 方法(GET 或 POST),以及此交互是否为异步交互。以上示例中的参数有:
- URL
autocomplete.php 和用户输入 complete-field 中的文本:
var url = "autocomplete.php?action=complete&id=" + escape(completeField.value);
GET,表示 HTTP 交互使用 GET 方法,以及
true,表示此交互是异步交互:
req.open("GET", url, true);
如果此交互设为异步交互,则必须指定回调函数。此交互的回调函数是使用以下语句进行设置的:
req.onreadystatechange = callback;
并且 稍后必须定义 callback() 函数。HTTP 交互在调用 XMLHttpRequest.send() 时开始。在以上 流程图中,此操作映射到发送给 Web 服务器的 HTTP 请求。
服务器端编程
NetBeans IDE 6.5 对使用 PHP 进行 Web 开发提供了全面支持。您可以使用 *AMP 包设置您的开发环境,以便从 IDE 进行快速而有效地编辑和部署。PHP 编辑器提供了标准的编辑功能,如代码完成、语法突出显示、标记实例、重构、代码模板、文档的弹出式提示、代码导航、编辑器警告和任务列表。有关快速演示,请参见 NetBeans PHP 编辑器截屏视频。对于需要数据库的应用程序,IDE 提供了对大部分主流数据库(特别是 MySQL)的广泛支持。有关详细信息,请参见 NetBeans MySQL 截屏视频和数据库集成功能。
您要为自动完成应用程序生成的业务逻辑需要处理请求,方法是检索数据存储中的数据,然后准备并发送响应。此操作在此处是使用名为 autocomplete 的 PHP 文件实现的。在您对文件进行编码之前,请设置数据存储和此文件访问数据所需的功能。
创建数据存储
对于这种简单的应用程序,您可以创建一个名为 ComposerData 的 PHP 类,在其中使用数组保留作曲家的数据。您还可以创建 Composer 类,使业务逻辑从数组所包含的条目中检索数据。
- 在“项目”窗口中右键单击项目节点,然后选择“新建”>“PHP 类”。
- 将类命名为
ComposerData,然后单击“完成”。此时会创建该类,并在 IDE 编辑器中将该类打开。
- 在此编辑器中,粘贴以下代码:
<?php
require "Composer.php";
class ComposerData {
public $composers;
function __construct() { $this->composers = array( new Composer("1", "Johann Sebastian", "Bach", "Baroque"), new Composer("2", "Arcangelo", "Corelli", "Baroque"), new Composer("3", "George Frideric", "Handel", "Baroque"), new Composer("4", "Henry", "Purcell", "Baroque"), new Composer("5", "Jean-Philippe", "Rameau", "Baroque"), new Composer("6", "Domenico", "Scarlatti", "Baroque"), new Composer("7", "Antonio", "Vivaldi", "Baroque"),
new Composer("8", "Ludwig van", "Beethoven", "Classical"), new Composer("9", "Johannes", "Brahms", "Classical"), new Composer("10", "Francesco", "Cavalli", "Classical"), new Composer("11", "Fryderyk Franciszek", "Chopin", "Classical"), new Composer("12", "Antonin", "Dvorak", "Classical"), new Composer("13", "Franz Joseph", "Haydn", "Classical"), new Composer("14", "Gustav", "Mahler", "Classical"), new Composer("15", "Wolfgang Amadeus", "Mozart", "Classical"), new Composer("16", "Johann", "Pachelbel", "Classical"), new Composer("17", "Gioachino", "Rossini", "Classical"), new Composer("18", "Dmitry", "Shostakovich", "Classical"), new Composer("19", "Richard", "Wagner", "Classical"),
new Composer("20", "Louis-Hector", "Berlioz", "Romantic"), new Composer("21", "Georges", "Bizet", "Romantic"), new Composer("22", "Cesar", "Cui", "Romantic"), new Composer("23", "Claude", "Debussy", "Romantic"), new Composer("24", "Edward", "Elgar", "Romantic"), new Composer("25", "Gabriel", "Faure", "Romantic"), new Composer("26", "Cesar", "Franck", "Romantic"), new Composer("27", "Edvard", "Grieg", "Romantic"), new Composer("28", "Nikolay", "Rimsky-Korsakov", "Romantic"), new Composer("29", "Franz Joseph", "Liszt", "Romantic"),
new Composer("30", "Felix", "Mendelssohn", "Romantic"), new Composer("31", "Giocomo", "Puccini", "Romantic"), new Composer("32", "Sergei", "Rachmaninoff", "Romantic"), new Composer("33", "Camille", "Saint-Saens", "Romantic"), new Composer("34", "Franz", "Schubert", "Romantic"), new Composer("35", "Robert", "Schumann", "Romantic"), new Composer("36", "Jean", "Sibelius", "Romantic"), new Composer("37", "Bedrich", "Smetana", "Romantic"), new Composer("38", "Richard", "Strauss", "Romantic"), new Composer("39", "Pyotr Il'yich", "Tchaikovsky", "Romantic"), new Composer("40", "Guiseppe", "Verdi", "Romantic"),
new Composer("41", "Bela", "Bartok", "Post-Romantic"), new Composer("42", "Leonard", "Bernstein", "Post-Romantic"), new Composer("43", "Benjamin", "Britten", "Post-Romantic"), new Composer("44", "John", "Cage", "Post-Romantic"), new Composer("45", "Aaron", "Copland", "Post-Romantic"), new Composer("46", "George", "Gershwin", "Post-Romantic"), new Composer("47", "Sergey", "Prokofiev", "Post-Romantic"), new Composer("48", "Maurice", "Ravel", "Post-Romantic"), new Composer("49", "Igor", "Stravinsky", "Post-Romantic"), new Composer("50", "Carl", "Orff", "Post-Romantic"), ); } }
?>
创建 Composer 类:
- 在“项目”窗口中右键单击项目节点,然后选择“新建”>“PHP 类”。
- 将类命名为
Composer,然后单击“完成”。此时会创建该类,并在编辑器中将该类打开。
- 在此编辑器中,粘贴以下代码:
<?php
class Composer { public $id; public $firstName; public $lastName; public $category;
function __construct($id, $firstName, $lastName, $category) { $this->id = $id; $this->firstName = $firstName; $this->lastName = $lastName; $this->category = $category; } }
?>
创建业务逻辑
创建 PHP 文件以处理传入请求接收到的 autocomplete URL。
- 在“项目”窗口中右键单击项目节点,然后选择“新建”>“PHP 文件”。
- 将文件命名为
autocomplete,然后单击“完成”。此时会创建该文件,并在 IDE 编辑器中将该文件打开。
- 将以下代码输入文件中。
<?php
require_once("ComposerData.php");
session_start();
$composerData = new ComposerData(); $composers = $composerData->composers;
$results = array(); $namesAdded = false;
// simple matching for start of first or last name, or both if(isset($_GET['action']) && $_GET['action'] == "complete") { foreach($composers as $composer) { if(!is_numeric($_GET['id']) &&
// if id matches first name (stripos($composer->firstName, $_GET['id']) === 0 ||
// if id matches last name stripos($composer->lastName, $_GET['id']) === 0) ||
// if id matches full name stripos($composer->firstName." ".$composer->lastName, $_GET['id']) === 0) {
$results[] = $composer; } }
// prepare xml data if(sizeof($results) != 0) { header('Content-type: text/xml'); echo "<composers>"; foreach($results as $result) { echo "<composer>"; echo "<id>" . $result->id . "</id>"; echo "<firstName>" . $result->firstName . "</firstName>"; echo "<lastName>" . $result->lastName . "</lastName>"; echo "</composer>"; } echo "</composers>"; } }
// if user chooses from pop-up box if(isset($_GET['action']) && isset($_GET['id']) && $_GET['action'] == "lookup") { foreach($composers as $composer) { if($composer->id == $_GET['id']) { session_register("id"); session_register ("firstName"); session_register ("lastName"); session_register ("category");
$HTTP_SESSION_VARS ["id"] = $composer->id; $HTTP_SESSION_VARS ["firstName"] = $composer->firstName; $HTTP_SESSION_VARS ["lastName"] = $composer->lastName; $HTTP_SESSION_VARS ["category"] = $composer->category;
header("Location: composerView.php"); } } }
?>
正如您看到的,编写用于进行 Ajax 处理的服务器端的代码时并没有什么真正的新内容要了解。如果希望交换 XML 文档,则需要将响应内容类型设置为 text/xml。通过 Ajax,您还可以交换纯文本,甚至可以交换可在客户端由回调函数计算或执行的 JavaScript 片断。还请注意,有些浏览器可能会缓存结果,因此可能需要将 Cache-Control HTTP 头信息设置为 no-cache。
在此示例中,autocomplete.php 文件生成了一个 XML 文档,其中包含姓氏或名字以用户所键入的字符开头的所有作曲家。本文档会映射到以上流程图中所描述的 XML 数据。以下是返回到 XMLHttpRequest 对象的 XML 文档的示例:
<composers> <composer> <id>12</id> <firstName>Antonin</firstName> <lastName>Dvorak</lastName> </composer> <composer> <id>45</id> <firstName>Aaron</firstName> <lastName>Copland</lastName> </composer> <composer> <id>7</id> <firstName>Antonio</firstName> <lastName>Vivaldi</lastName> </composer> <composer> <id>2</id> <firstName>Arcangelo</firstName> <lastName>Corelli</lastName> </composer> </composers>
客户端编程:第 2 部分
您必须定义回调函数,以处理服务器的响应,同时添加一些必要的功能,以反映用户所查看页面中的更改。这需要修改 HTML DOM。最后,可以使用 IDE 的 CSS 编辑器将简单的样式表添加到该演示。
添加回调功能
在 XMLHttpRequest 对象的 readyState 属性发生更改时,回调函数会在 HTTP 交互过程中的某个特定点被异步调用。在您要生成的应用程序中,回调函数是 callback()。您可以回想一下,在 doCompletion() 中,callback 设置为某个函数的 XMLHttpRequest.onreadystatechange 属性。现在,按以下步骤实现回调函数。
- 在编辑器中打开
javascript.js,然后键入以下代码。
function callback() { if (req.readyState == 4) { if (req.status == 200) { parseMessages(req.responseXML); } else if (req.status == 204){ clearTable(); } } }
readyState 为 "4" 表示 HTTP 交互完成。XMLHttpRequest.readState 的 API 表示可以设置 5 个值。它们是:
| 0 |
未初始化 |
| 1 |
正在装入 |
| 2 |
已装入 |
| 3 |
交互中 |
| 4 |
完成 |
请注意,当 XMLHttpRequest.readyState 为 "4" 时会调用 parseMessages() 函数。您将在接下来的更新 HTML DOM 部分定义此函数。status 指该请求的 HTTP 状态代码定义 -- "200" 表示成功,而 "204" 表示“无内容”状态。
更新 HTML DOM
parseMessages() 函数用于处理传入的 XML 数据。为了实现此功能,它需要依靠若干附属的函数,如 appendComposer()、getElementY() 和 clearTable()。您还必须向此索引页引入新的元素(如用作自动完成框的另一个 HTML 表格),以及元素的 ID,以便它们可以在 javascript.js 中引用。最后,创建对应于 index.php 中元素 ID 的新变量,并且在之前实现的 init() 函数中对其进行初始化,然后添加每次装入 index.php 时所需要的一些功能。
注意:您在以下步骤中创建的函数和元素之间存在相互依赖关系。建议您完成此部分,然后在代码全部完成之后检查此代码。
- 在编辑器中打开
index.php,并在您之前创建的 HTML 表格的第二行键入以下代码。
<tr> <td id="auto-row" colspan="2"> <table id="complete-table" /> <td/> </tr>
此表格的第二行包含其他 HTML 表格。此表格表示将用于填写作曲家名字的自动完成框。
- 在编辑器中打开
javascript.js,并在文件顶部添加以下三个变量。
var completeField; var completeTable; var autoRow;
- 将以下行(以粗体显示)添加到
init() 函数中。
function init() { completeField = document.getElementById("complete-field"); completeTable = document.getElementById("complete-table"); autoRow = document.getElementById("auto-row"); completeTable.style.top = getElementY(autoRow) + "px"; clearTable(); }
init() 的一个作用是使将修改索引页的 DOM 的其他函数可以访问 index.php 内的元素。
- 将
appendComposer() 添加到 javascript.js。
function appendComposer(firstName,lastName,composerId) {
var row; var cell; var linkElement;
completeTable.style.display = 'table'; if (isIE) { row = completeTable.insertRow(completeTable.rows.length); cell = row.insertCell(0); } else { row = document.createElement("tr"); cell = document.createElement("td"); row.appendChild(cell); completeTable.appendChild(row); }
cell.className = "popupCell";
linkElement = document.createElement("a"); linkElement.className = "popupItem"; linkElement.setAttribute("href", "autocomplete.php?action=lookup&id=" + composerId); linkElement.appendChild(document.createTextNode(firstName + " " + lastName)); cell.appendChild(linkElement); }
此函数创建了一个新的表行,并用其所含的三个参数传递的数据将指向作曲家的链接插入此表行中,然后将此行插入索引页的 complete-table 元素中。
- 将
clearTable() 添加到 javascript.js。
function clearTable() { if (completeTable) { completeTable.style.display = 'none'; for (loop = completeTable.childNodes.length -1; loop >= 0 ; loop--) { completeTable.removeChild(completeTable.childNodes[loop]); } } }
此函数用于将 complete-table 元素的显示方式设置为“无”(也就是使其不可见),并删除所有已创建的现有作曲家名字条目。请注意,为了在缺省情况下将此表格设置为不可见,会在 init() 中调用此函数。
- 将
getElementY() 添加到 javascript.js。
function getElementY(element){
var targetTop = 0;
if (element.offsetParent) { while (element.offsetParent) { targetTop += element.offsetTop; element = element.offsetParent; } } else if (element.y) { targetTop += element.y; } return targetTop; }
此函数用于查找父元素的垂直位置。这是必要的,因为此元素的实际位置(如果显示)通常根据浏览器的类型和版本而定。请注意,如果 complete-table 元素显示包含作曲家名字,则会移动到其所在表格中的右下角。
注意:请在 http://www.quirksmode.org/ 上查看 offset 的说明。
- 修改
doCompletion() 函数,以便在文本字段为空时,删除自动完成框中显示的任何作曲家条目(更改的内容以粗体显示)。
function doCompletion() { if (completeField.value == "") { clearTable(); } else { var url = "autocomplete.php?action=complete&id=" + escape(completeField.value); req = initRequest(url); req.open("GET", url, true); req.onreadystatechange = callback; req.send(null); } }
- 将
parseMessages() 添加到 javascript.js。
function parseMessages(responseXML) { clearTable(); var composers = responseXML.getElementsByTagName("composers")[0]; if (composers.childNodes.length > 0) { completeTable.setAttribute("bordercolor", "black"); completeTable.setAttribute("border", "1"); } else { clearTable(); }
for (loop = 0; loop < composers.childNodes.length; loop++) { var composer = composers.childNodes[loop]; var firstName = composer.getElementsByTagName("firstName")[0]; var lastName = composer.getElementsByTagName("lastName")[0]; var composerId = composer.getElementsByTagName("id")[0]; appendComposer(firstName.childNodes[0].nodeValue, lastName.childNodes[0].nodeValue, composerId.childNodes[0].nodeValue); } }
parseMessages() 函数作为参数接收 autocomplete.php 文件返回的 XML 文档的对象表示。此函数以编程方式遍历 XML 文档,提取每个条目的 firstName、lastName 和 id,然后将数据传递到 appendComposer()。这将导致动态更新 complete-table 元素的内容。例如,已生成并插入 complete-table 中的条目如下所示:
<tr> <td class="popupCell"> <a class="popupItem" href="autocomplete?action=lookup&id=12">Antonin Dvorak</a> </td> </tr>
对 complete-table 元素的动态更新是使用 Ajax 进行通信的过程中所产生的通信过程流的最后一步。此更新会映射到正在发送给以上流程图中表示的 HTML 和 CSS 数据。
附加样式表
在此阶段,您已完成了实现此应用程序功能所需的所有代码。要查看您的努力成果,请立即尝试运行此应用程序。
- 在“项目”窗口中,右键单击该项目节点并选择“运行”。此项目会重新编译,并部署到目标服务器。此时您的浏览器会打开,并可以查看索引页。

要向您的应用程序添加一个样式表,只需创建 .css 文件,并从您的表示页面链接到此文件。当您使用 .css 文件时,IDE 会为您提供代码完成支持,以及其他一些有助于生成样式表规则的功能。其中包括:
- 样式规则编辑器:通过此对话框,您可以基于类、ID 和 HTML 元素创建规则,并在文档分层结构中设置其位置。
- CSS 预览窗口:如果您将光标放置在某个规则中,此预览窗口就会显示根据此规则的声明块所呈现的样例文本。
- CSS 样式生成器:此界面旨在让您可以使用所选的控件和小部件创建规则。
要向您的应用程序添加样式表,请按以下步骤操作。
- 在“项目”窗口中,右键单击项目节点,然后选择“新建”>“层叠样式表”(如果“层叠样式表”未列出,则选择“其他”。然后从“新建文件”向导的 "Web" 类别中选择“层叠样式表”。)
- 在“CSS 文件名”文本字段中,键入
stylesheet。
- 单击“完成”。此时新文件会添加到“项目”窗口中,并在 IDE 的编辑器中打开。
- 在
stylesheet.css 中,键入以下规则。您可以使用 IDE 的代码完成支持,方法是:在希望查看建议时按 Ctrl-空格键。
body { font-family: sans-serif; font-size: smaller; padding: 50px; color: #555; width: 650px; }
h1 { letter-spacing: 6px; font-size: 1.6em; color: #be7429; font-weight: bold; }
h2 { text-align: left; letter-spacing: 6px; font-size: 1.4em; color: #be7429; font-weight: normal; width: 450px; }
table { width: 550px; padding: 10px; background-color: #c5e7e0; }
td { padding: 10px; }
a { color: #be7429; text-decoration: none; }
a:hover { text-decoration: underline; }
.popupBox { position: absolute; top: 170px; left: 140px; }
.popupCell { background-color: #fffafa; }
.popupCell:hover { background-color: #f5ebe9; }
.popupItem { color: #333; text-decoration: none; font-size: 1.2em; }
对 CSS 代码的有效性执行检查,方法是右键单击 CSS 编辑器,然后选择“检查 CSS”。遇到的任何错误都会显示在“输出”窗口中(“窗口”>“输出”)。
- 选择“窗口”>“其他”>“CSS 预览”,打开“CSS 预览”窗口。
- 将光标置于对文本和颜色进行调整的规则(如
h1)中。此时“CSS 预览”窗口会生成一个样例显示,说明文本将在浏览器中的呈现方式。

- 切换到编辑器中的
index.php 页面,并在 <head> 标记之间添加对样式表的引用。
<link rel="stylesheet" type="text/css" href="stylesheet.css">
现在,当您再次运行此应用程序时,它会使用您刚创建的样式表显示在浏览器中。每次您键入字符时,都会向服务器发送异步请求,并返回 AutoCompleteServlet 准备好的 XML 数据。随着您输入的字符增多,为了反映匹配项的新列表,作曲家名字的数量会越来越少。
小结
以下内容对 Ajax 简介进行了小结。希望现在您已经明白了 Ajax 只是在后台通过 HTTP 交换信息,并基于结果动态地更新该页面。
您可能注意到所生成的应用程序存在许多缺点,例如从自动完成框选择作曲家名字时没有反应!欢迎您下载样例应用程序以了解它是如何使用 PHP 技术实现的。此外,您可能想要调查使用户无法请求数据存储中不存在的名字的验证。通过学习 NetBeans PHP 学习资源中的其他教程,可以更多地了解这些技术。
另请参见
有关 netbeans.org 上 Ajax 和 PHP 技术的详细信息,请参见以下资源:
|
|