本文是使用 Ajax 改造现有 Web 站点系列的第一篇文章,将展示如何使用简单的模式窗口(modal window)消除弹出窗口和导航死角。
Ajax 技术改变了大型商业 Web 应用程序的外观,但是许多较小的 Web 站点都不具备足够的资源重新构建完整的用户界面(UI)。Ajax 的一些新特性能够解决实际中的界面问题并改善用户体验。本文将展示如何使用简单的模式窗口消除弹出窗口和导航死角。通过应用渐进增强(progressive enhancement)这一理念,能够保证这些增强的 UI 特性不会损害站点的可访问性,并且严格遵守 Web 标准。
本文假设您已经牢固掌握超文本标记语言(Hypertext Markup Language,HTML)和级联样式表(Cascading Style Sheet,CSS),基本了解 JavaScript 编程和 Ajax。示例应用程序仅使用客户端代码构建;本文演示的技术适用于任何服务器端应用程序框架。要运行示例站点,您至少需要在本地主机上运行一个基本的 Web 服务器。此外,您也可以仅跟随源代码并在我的 Web 服务器上查看运行中的示例站点(参见 参考资料 中的链接)。
引导用户跟随特定路径 — 即,从产品搜索到付款购买 — 这种需求与 Web 本身的历史一样久。它一直都充满着风险:让用户迷失方向。您的导航路径越长、越复杂,用户经历的内容就越多。您需要为用户提供足够的信息,以防止他们在导航过程中失去兴趣。
在 Web 1.0 世界,购物站点通过构造一条流畅的路径(从搜索和结果到选择和购买)流线化用户体验。当购买路径提供的信息无法满足用户需求时,他们需要通过导航找到提供 更多信息的产品细节或比较页面。这种方法存在的问题是,它们使用户离开了购买路径,增加了用户放弃购买的机会。而且还难以维护,因为您的导航逻辑必须存储 与用户如何到达此死角相关的信息。
弹出窗口似乎提供了一个解决方案。通过弹出窗口提供补充信息,主窗口中直接的分布路径不会受到干扰。然而,不幸的是,弹出窗口容易使人混淆和反感。它们可能比上面的导航弯路更容易维护,但是它们很可能使用户退出您希望其完成的购买流程。
幸 运的是,开源 JavaScript 库提供了一种简单方式,可以彻底摆脱导航弯路和弹出窗口。本文将演示如何使用 Ajax 和 Dynamic HTML (DHTML) 技术在工具提示、lightbox 和其他模式窗口中呈现补充信息。由于这些元素可以动态地插入任何页面,它们能够保持从主页到购买的快速、分步路径。
应用程序介绍:Customize Me Now
本文中的示例应用程序主要针对电子商务。我已经构造了一个虚构的购物应用程序 Customize Me Now,允许用户定制和购买一组不同的产品:批萨、旅行包或有价证券。当然,在实际中,这些产品类别绝不会出现在同一个站点上。但是,将它们放在一起可以演示许多站点面对的复杂、真实的导航难题。
本 文首先提供一个 Web 1.0 版的 Customize Me Now,然后将其改进为 Web 2.0 版,当您了解到补充信息只是通过一个 Ajax 调用提供时,就能想象到导航路径有多么的流畅。此处涉及的技术适合于任何需要保持简单性并能引导用户的流程。配置产品、做一个调查、注册一些服务,或者只 是完成一个注册表单 — 所有这些流程都可以使用 Ajax 实现流线化。
现在,也许不再需要介绍 Ajax 了:在 Web 开发领域到处都是它身影。这些年来,聪明的编程人员一直使用 JavaScript 代码逐步更新 Web 页面,而不再与服务器往返通信。但仅仅是因为 xmlHttpRequest 对象的采用 — 最初是一个 Windows® Internet Explorer® 扩展,但现在支持许多不同的浏览器 — 才使 Ajax 流行起来的。无论何时,只要您看到一个与桌面应用程序非常相似的 Web 应用程序,那么它很可能采用了 Ajax。本文无意讨论 Ajax 编程的基础知识,但是您将使用到许多使用 Ajax 技术的开源库。
Ajax UI 通常使用工具提示、lightbox 和模式窗口。它们都是指一个浏览器视区(viewport)的弹出屏幕,而不是在一个独立的窗口中运行。工具提示(Tooltips)通常是一些提供上下文内容的小型窗口,将鼠标悬停在一个触发器元素上就会显示。模式窗口(Modal windows)通常比较大,而且通过一个单击事件触发。Lightbox 是一种特殊的模式窗口,它通过半透明的重叠将窗口的原始内容和模式内容分隔开。任何一种这类容器都可以填充各种内容:使用 DHTML 技术隐藏的内联内容;通过 Ajax 调用从服务器拉取的新内容;或者拉入 iframe 中的完整的独立文档。流行的 DVD 租赁服务 Netflix 提供了一个关于这些界面元素的出色示例。
工具介绍:jQuery、GreyBox、ThickBox、JTip 和 jQuery 表单
自 从 2005 年 Ajax 开始流行之后,开源 JavaScript 工具箱不断增多。每个工具箱都有自己的优点、缺陷和特性,但是出色的工具箱隐藏了浏览器的差异,并提供了一个针对 Ajax、DHTML 和视觉效果的出色的跨浏览器应用程序编程接口(API)。一些解决方案(比如 Google Web Toolkit)使用服务器端 Java™ 代码自动生成客户端 JavaScript 代码。但是,大多数都使用本机 JavaScript 库。
您将使用一个这样的库,jQuery。自从 2006 年首次登场,jQuery 因其优雅的 API 和谦逊的 JavaScript 而变得非常流行。使用 jQuery,几乎无需对服务器代码、HTML 标记或 CSS 进行任何更改,您就可以将一个未使用 Ajax 的 Web 1.0 站点转变为一个通过 Ajax 增强的 Web 2.0 站点。在运行时,您的 JavaScript 代码将会在浏览器内部转换现有的 HTML 元素和行为。如果 JavaScript 被禁用或者不受浏览器支持,标记将会按原来的方式运行。这种渐进增强 原理可以确保您的 Web 应用程序仍然能够被广大用户访问。物理条件较差的移动设备、辅助性软件,或者甚至是 10 年前的 Web 浏览器:所有这些都能够运行您的应用程序。
除 了支持渐进增强之外,jQuery 还允许您利用大型的、活跃的插件开发人员社区。许多 JavaScript 工具箱都试图预测所有可能的开发人员需求,但是 jQuery 只关注基本原理。其核心库仍然很简洁,而附加功能是通过开源社区的插件来提供的。具体来讲,您可以利用以下插件:
ThickBox:由 Cody Lindley 开发
jQuery Forms:这是由 jQuery 社区合作开发
JTip:由 Cody Lindley 开发,并由 jQuery 社区进行扩展
GreyBox:由 Amir Salihefendic 开发
了解应用程序:Customize Me Now 1.0
以下小结帮助您了解 Customize Me Now 1.0 — 它的用户体验和源代码。
用户体验
图 1 展示了 Customize Me Now Results 页面和一个信息弹出窗口。它演示了站点能够向用户提供的与他们定制的产品有关的信息。尽管最佳的用户路径是从搜索和结果到定制和购买的直线路径,但该界面 却提供了一些迂回的路径。站点使用传统的弹出窗口显示每个产品和产品选项的一小段上下文信息。单击 Pizza,您将会看到关于站点的批萨产品的信息。单击 Cheese,您将会看到关于您的批萨可用的奶酪的信息。此外,用户可以导航到厂商的 Web 站点 — 同样通过弹出窗口呈现。
图 1. Results 页面 1.0
如 果用户想要获得更多信息,站点就会提供一个 Product Details 页面,其中包括每个产品的更详细信息 —— 图片、文章、用户评论等等。最后,如果用户想要将一个产品与其他产品进行比较,他可以在 Comparison 页上逐个查看这些产品。在这些资源中进行导航非常复杂。由于用户需要定制每个产品,很难在每步操作中都提供一个 Add to cart 链接。站点鼓励用户定制、然后添加到购物车中。但是也允许用户跳过这些步骤,使用一组默认选项添加到购物车,在稍后进行定制。
图 2 展示了 Customize Me Now 1.0 的站点地图。它显示了用户的路径非常复杂。大多数屏幕都链接到至少 2 或 3 个其他屏幕。
图 2. Customize Me Now 1.0 站点地图
代码
Customize Me Now 的功能演示代码只提供了客户端部分:HTML CSS、JavaScript 代码和图像文件。在实际中,您显然还需要一个大型的服务器端组件:Microsoft® ASP.NET、Java 技术、Ruby on Rails、Django 或 PHP。但是 jQuery 的美妙之处在于,它纯粹关于客户端。您可以使用 Ajax 简化您的用户体验,无需服务器端组件。我没有提供任何服务器端代码,因为这些细节对于这个项目无关紧要。您只需知道当您打开一个 HTML 文件时,就会有一个 PHP 模板、一个 JavaServer Pages™ (JSP) 文件或任何其他将 HTML 发送到服务器的文件。
下载了 1.0 版应用程序的源代码之后,请看一下其中一个页面的标记。它应该与清单 1 类似。
清单 1. results.html 1.0 的 HTML 代码
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Customize Me Now: Search Results</title>
<link rel="stylesheet" type="text/css" href="../css/customizemenow.css"/>
</head>
<body id="CMN">
<!--[header goes here]-->
<div id="main">
<form method="GET" action="comparison.html">
<h1>Search Results</h1>
<div class="buttons">
<input class="button" type="submit" name="submitTop" id="submitTop"
value="Compare Selected Products" />
or <a href="index.html">search again</a>
</div>
<table class="searchResults">
<thead>
<tr>
<th>Product</th>
<th>Description</th>
<th>Options</th>
<th>Compare</th>
<th>Actions</th>
</tr>
</thead>
<tr>
<td class="name">
<a target="productPopup"
href="productPopup.html?product=A">Pizza</a>
</td>
<td class="desc">
A delicious Italian treat.<br />
[<a href="detail.html?product=A">full product details</a>]
</td>
<td class="options">
<ul>
<li>
<a target="optionsPopup"
href="optionsPopup.html?product=A">crust</a>
</li>
<li>
<a target="optionsPopup"
href="optionsPopup.html?product=A">cheese</a>
</li>
<li>
<a target="optionsPopup"
href="optionsPopup.html?product=A">toppings</a>
</li>
</ul>
</td>
<td class="action">
<input type="checkbox" target="productPopup" name="compareA"
id="compareA" value="true" checked="checked"/>
</td>
<td class="action">
<a class="button" href="customize.html?product=A">customize
product</a>
<a class="button" href="cart.html?product=A">add to cart with
default options</a>
</td>
</tr>
<!--[additional table rows go here]-->
</table>
<div>
<div class="buttons">
<input class="button" type="submit" name="submitBottom" id="submitBottom"
value="Compare Selected Products" />
or <a href="index.html">search again</a>
</div>
</form>
</div>
<!--[footer goes here]-->
</body>
</html>
返回炫浪学院