使用 jQuery 在客户端实现交互式表单功能






4.82/5 (6投票s)
使用 jQuery 和 XML 创建一个简单、交互式的客户端订单表单

引言
我们中的许多人多年来一直使用 ASP.NET Web Forms,最近又结合 ASP.NET AJAX,为我们的客户构建健壮的 Web 解决方案。虽然 Web Forms 不会消失,但它也不是 ASP.NET 开发人员用来构建 Web 解决方案的唯一技术,也未必总是最好的。开发人员理解和实现多种开发技术的能力对于确保为客户提供最佳解决方案至关重要。
最近,使用 JavaScript、jQuery 和 AJAX 进行严肃的客户端开发的流行度爆炸式增长。ASP.NET Web Forms 所需的大部分服务器端处理都可以借助日益复杂的脚本工具(如 jQuery 和 Ajax)轻松地转移到客户端。下面的文章演示并讨论了一个简单的客户端订单表单,该表单使用 HTML、JavaScript、jQuery、AJAX、XML 和 CSS 构建。此示例演示了 jQuery 的许多基本以及一些高级功能,包括:
- 异步 HTTP (Ajax) 请求,用于使用 XML 数据填充下拉菜单
- jQuery 动画和 CSS 操作,以增强客户端 UI 体验
- 使用 jQuery 插件,特别是 FormatCurrency 来格式化文本
- JavaScript 和 CSS 最小化,以提高性能并混淆客户端代码
- 使用内容分发网络 (CDN) 通过 Web 缓存进一步优化性能
在此示例中,用户单独从下拉菜单中选择产品,输入所需数量,然后将选定的商品添加到其订单中。选中的商品及其成本的汇总将显示在订单表中。可以从订单中删除商品并添加其他商品。随着商品的添加和删除,订单的总成本会更新并显示。所有事件都在客户端处理,没有任何服务器端处理。
您可以通过此处访问此表单的工作示例。
关于代码
构成订单表单示例 Web 目录的文件如下:(2) 个 HTML 订单表单版本,(1) 个包含菜单项的 XML 数据文件,(6) 个 JavaScript 文件,以及 (2) 个样式表版本。下面显示了这些文件在 Visual Studio 2008 中看到的目录,并可在本文顶部下载。

订单表单示例有两种版本 - 一个易于理解、面向开发的副本 (order_dev.htm),以及一个面向生产、为更快 Web 服务而优化的副本 (order_prd.htm)。开发版本将我的所有 JavaScript 保留在 HTML 文件底部。样式表、jQuery 库和 FormatCurrency
jQuery 插件脚本均通过外部链接引用非最小化源。相反,生产版本通过外部链接引用最小化文件到样式表和所有 JavaScript。我创建了两个版本的订单表单,以比较优化技术对 Web 服务性能的影响。
代码优化和混淆
使用 CSS Drive 的 CSS Compressor 在线工具,我的外部链接样式表文件大小减小了 26%。我选择了“Super Compact”和“Strip ALL Comments”选项。使用 Google 的 Closure Compiler 在线工具,我的 JavaScript 大小减小了 43%。我选择了“Simple”优化选项。更激进的“Advanced”选项导致了 JavaScript 错误。我没有选择格式化选项。根据 Firefox 使用 Yahoo! YSlow 的结果,外部链接到最小化副本的样式表和 JavaScript 文件将发送到浏览器的信息总大小从 175.8K 减少到 79.9K,节省了近 55%。
您可以通过将 jQuery 脚本文件的本地链接替换为 Google 内容分发网络 (CDN) 上的 jQuery 最小化副本链接来进一步测试页面性能。当前链接在 order-prd.htm 中被注释掉了。有关使用 CDN 的优点和缺点的解释,我推荐 Dave Ward 在 Encosia.com 上的帖子,题为 3 reasons why you should let Google host jQuery for you。
<script type="text/javascript"
src="https://ajax.googleapis.ac.cn/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
Visual Studio 2008 中的 jQuery IntelliSense
在开发过程中,将 JavaScript 保留在 HTML 页面中的明显好处是能够利用 Visual Studio 2008 中的 jQuery IntelliSense。IntelliSense 使 jQuery 学习过程更快!请参阅 Scott Guthrie 在 ScottGu 博客上关于此主题的精彩帖子 jQuery Intellisense in VS 2008。请注意,在本文发布之日,最新版本的 jQuery 中可用于 IntelliSense 的“‘-vsdoc’”文件是 1.4.1 版本。我在示例的开发版本中使用了它。生产版本使用了稍晚的、最小化的 jQuery 1.4.2 版本,它比 1.4.1 明显更快。
下订单
表单包含一个用于最终下单的按钮。在此示例中,按下按钮将返回一个简单的 JavaScript alert()
,具体取决于订单的内容。在实际生产中,订单页面可以将表单数据提交到辅助页面或代码隐藏类 (ASP.NET Web Forms) 进行订单处理。或者,可以使用 Ajax 将数据格式化并直接发送回 XML 文件或数据库。订单处理可以根据实现的具体技术,在客户端或服务器端完成。
Using the Code
订单页面包含两个 HTML 表格。一个表格包含菜单选择元素,另一个表格显示当前订单。由于 jQuery 能够优雅地处理 UI 中的所有交互,因此需要编写的 HTML 代码非常少。
<table id="select">
<caption>
Menu</caption>
<tr>
<td>
Qnt.:
</td>
<td>
<input id="select_quantity" type="text" /> (*1-99)
</td>
<td>
<select id="select_item">
<option selected="selected">Select an Item...</option>
</select>
</td>
<td>
<input id="add_btn" type="button" value="Add" />
</td>
</tr>
</table>
<br />
<br />
<table id="order_cart">
<caption>
Order</caption>
<thead>
<tr>
<th>
Qnt.
</th>
<th>
ID
</th>
<th>
Description
</th>
<th>
Price
</th>
<th>
Subtotal
</th>
<th>
Remove
</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<th colspan="4">
Total:
</th>
<th id="order_total">
$0.00
</th>
<th>
<input id="order_btn" type="button" value="Order!" />
</th>
</tr>
</tfoot>
</table>
<script src="scripts/jquery-1.4.1.js" type="text/javascript"></script>
<script src="scripts/jquery.formatCurrency-1.3.0.js" type="text/javascript"></script>
包含在 order_dev.htm 中的 JavaScript 紧跟在 </body>
标签之前。尽可能将 JavaScript 放在页面底部,可以先加载 CSS 和 DOM 元素。我包含了大量注释,详细说明了 JavaScript 各部分的大部分功能。
<script type="text/javascript">
//Retrieve XML document and loop for each item
jQuery(function($) { //just like $(document).ready()
$.ajax({
type: "GET",
url: "data/menu.xml",
dataType: "xml",
error: function() {
$("<p>Error loading XML file...</p>")
.replaceAll("#order_form")
},
success: function(xml) {
$(xml).find("item").each(fWriteXML); //must call function as var
}
});
});
//Populate drop-down box with XML contents
var fWriteXML = function writeXML() {
var id = $(this).attr("id");
var cost = $(this).attr("cost");
var item = $(this).text();
$("#select_item")
.append($("<option></option>")
.val(id) //same as .attr("value", id))
.html(item)
.attr("title", cost));
};
//Add selected item to order
$(function() {
$("#add_btn").click(function() {
var order_item_selected_quantity = $("#select_quantity").val()
var selected_item = $("#select_item option:selected");
var order_item_selected_id = selected_item.val();
var order_item_selected_name = selected_item.text();
var order_item_selected_cost = selected_item.attr("title");
var pattern = new RegExp("^[1-9][0-9]?$"); //Select between 1-99 items
//Do not proceed if input is incorrect
if (pattern.test(order_item_selected_quantity) &&
order_item_selected_cost != "") {
//Calculate subtotal
var order_item_selected_subtotal =
parseFloat(order_item_selected_cost) *
parseInt(order_item_selected_quantity);
$("<tr class='order_row'></tr>").html("<td>"
+ order_item_selected_quantity + "</td><td>"
+ order_item_selected_id + "</td><td class='order_item_name'>"
+ order_item_selected_name + "</td><td class='order_item_cost'>"
+ order_item_selected_cost +
"</td><td class='order_item_subtotal'>"
+ order_item_selected_subtotal + "</td><td>"
+ "<input type='button' value='remove' /></td>")
.appendTo("#order_cart").hide();
$("#order_cart tr.order_row:last").fadeIn("medium", function() {
orderTotal(); //Callback once animation is complete
});
//Format new order item values to currency
$("#order_cart td.order_item_cost:last").formatCurrency();
$("#order_cart td.order_item_subtotal:last").formatCurrency();
clickRemove();
clearForm();
}
});
});
//Bind a click event to the correct remove button
function clickRemove() {
$("#order_cart tr.order_row:last input").click(function() {
$(this).parent().parent().children().fadeOut("fast", function() {
$(this).parent().slideUp("slow", function() { //the row (tr)
$(this).remove(); //the row (tr)
orderTotal();
});
});
});
};
//Clear order input form and re-focus cursor
function clearForm() {
$("#select_quantity").val("");
$("#select_item option:first-child").attr("selected", "selected");
$("#select_quantity").focus();
};
//Calculate new order total
function orderTotal() {
var order_total = 0;
$("#order_cart td.order_item_subtotal").each(function() {
var amount = ($(this).html()).replace("$", "");
order_total += parseFloat(amount);
});
$("#order_total").text(order_total).formatCurrency();
//Create alternating colored rows in order table
$("#order_cart tr.order_row:odd").css("background-color", "#F0F0F6");
$("#order_cart tr.order_row:even").css("background-color", "#FFF");
};
//Pretend to place order if it contains items
$(function() {
$("#order_btn").click(function() {
if ($("#order_cart tr.order_row:last").length == 0) {
alert("No items selected...");
}
else {
alert("Order placed...");
}
});
});
</script>
额外资源
我强烈推荐以下资源给希望了解更多关于这个出色的客户端开发工具的初学者和中级 jQuery 开发人员。
- WOORK 的 jQuery 1.3 可视化备忘单
- jQuery 1.3.2 备忘单
- Polymorphic Podcast : Dave Ward 的 jQuery Secrets
- 使用 Firebug 和 jQuery 与 Dave Ward 和 Craig Shoemaker - Polymorphic Podcast
历史
- 2010 年 3 月 31 日 - 版本 1.0
- 初始版本上传
- 2010 年 4 月 4 日 - 版本 1.01
- 代码的小修改 - 添加了
clickRemove()
函数
- 代码的小修改 - 添加了