您的位置:首页 > 其它

实现Web页面中级联菜单的设计/实现动态加载列表框/实现自动刷新页面/实现Web页面的局部动态更新/实现自动完成功能

2007-11-16 23:46 1421 查看
在Web页面中经常需要实现如图5-2所示的级联菜单的效果。即根据用户的选择,动态展开并显示出对应选项子菜单中的内容。本例中是根据用户所选择的商品类别信息,在子菜单中显示对应的商品名称。



图5-2 级联菜单的效果
在传统的Web实现方式中,一般是在页面初始化时动态获取到服务器端数据库中对应所有子菜单中的信息,放置页面中对应的位置,然后在结合CSS层叠样式表动态控制对应子菜单的显示或者隐藏。
采用这种方法的弊端在于会造成浏览器端下载的页面非常臃肿,许多根本用不到的信息也必须提前装载到页面中。
而如果借助Ajax技术,我们可以实现当用户选择对应的菜单项后,将对应的请求以异步方式提交到服务器端,然后有选择地从服务器端获取到对应的子菜单信息,再返回浏览器端进行响应显示。
首先在Eclipse中新建一个Web项目,项目名称为P52_Menu,对应的浏览器端页面代码如下:
源文件:menu.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
<LINK href="images/css.css" type=text/css rel=stylesheet>
</head>
<script language="javascript">
var XMLHttpReq;
var currentSort;
//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
elseif (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e){
try{
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
//发送请求函数
function sendRequest(url) {
createXMLHttpRequest();
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
}
// 处理返回信息函数
function processResponse() {
if(XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
updateMenu();
}else{ //页面不正常
alert("您所请求的页面有异常。");
}
}
}
//更新菜单函数
function updateMenu() {
var res=XMLHttpReq.responseXML.getElementsByTagName("res")
var subMenu = "";
for(var i = 0; i < res.length; i++) {
subMenu = subMenu + "  " + res[i].firstChild.data + "<br>";
}
currentSort.innerHTML = subMenu;
}
// 创建级联菜单函数
function showSubMenu(obj) {
currentSort =document.getElementById(obj);
currentSort.parentNode.style.display = "";
sendRequest("menu?sort=" + obj);
}

</script>

<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=0 width=200 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19><B>笔记本品牌</B>
</TD>
</TR>
<tr>
<td height="20">
<a onClick="showSubMenu('IBM')">IBM</a>
</td>
</tr>
<tr style="display:none">
<td height="20" id="IBM"> </td>
</tr>
<tr>
<td height="20">
<a onClick="showSubMenu('SONY')">SONY</a>
</td>
</tr>
<tr style="display:none ">
<td id="SONY" height="20"> </td>
</tr>
</table>
在该页面中提供了对应的菜单以供用户进行选择,用户选择菜单后,将调用“showSubMenu('XXX')函数,该函数带参数,其中参数用于传递所选菜单项的标志信息,以决定获取服务器端的哪个子菜单信息。在“showSubMenu('XXX')函数中首先获取到所选菜单项的识别信息,然后再借助Ajax提交请求,并同时提交用户所选菜单的标识信息到服务器端,等待服务器端的处理。当服务器端处理完成后,将返回对应的子菜单信息,在Ajax提供的处理函数中对应菜单项的位置进行显示,这里用innerHTML属性实现定位显示。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“menu”请求时,将由服务器端的类名为“classmate.MenuAction的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.MenuAction</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/menu</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>menu.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序MenuAction.java中对应的程序代码。当接收到浏览器端提交的请求后,Servlet程序将首先获取浏览器端提交的所选菜单项的标志信息,即所选择的商品类别信息,然后借助封装了数据库操作的JavaBean完成数据库的查询工作,依据类别获取到对应商品名称的信息。
package classmate;

import java.io.IOException;
……
public class MenuAction extends HttpServlet {

public void init(ServletConfig config) throws ServletException {
}

/*
* 处理<GET> 请求方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置接收信息的字符集
request.setCharacterEncoding("UTF-8");
//接收浏览器端提交的信息
String sort = request.getParameter("sort");
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");

//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
//查找该品牌具体型号
strSql = "select product.name from sort,product where sort.id=product.sortid
and sort.name='"+ sort + "'";

rs = db.executeQuery(strSql);
try {
while (rs.next()) {
out.println("<res>" + rs.getString("name") + "</res>");
}
}catch (SQLException e) {
e.printStackTrace();
}

out.println("</response>");
out.close();
}
}
注意在本例中,返回的XML文档的格式如下所示:
<response>
<res>商品名称1</ res>
<res>商品名称2</ res>
</response>
提示:读者可以进一步完善该程序,实现从服务器端动态获取菜单项信息,然后再依据用户选择动态显示子菜单信息的效果。这里所说的刷新,指的是通过重发URL请求来从服务器获得更新的数据以更新视图的显示。

实现动态加载列表框
本例中所实现的效果如图5-3所示。当用户在品牌选择的下拉列表框中选择了对应品牌后,该品牌下所有的商品信息将会动态出现在商品选择列表框中以供用户进一步选择。这种表单元素之间的联动效果在网页中非常常用。例如,随着所选专业,显示班级选择列表。随着所选部门,显示职务选择列表等。
传统的Web实现方式,页面初始化时准备好所有列表框中的信息,并通过逻辑控制建立列表框之间对应选项的联系。再依据用户的选择,通过逻辑判断将事先准备好的列表框信息装入对应的联动列表框中。
这种方法的弊端是造成浏览器端下载的页面非常臃肿,许多在本次交互中根本用不到的信息也必须提前装载到页面中。



图5-3 动态加载列表框的效果
借助Ajax技术,可以实现当用户选择第一个列表框中对应的选项后,将对应的请求以异步方式提交到服务器端,然后有选择地从服务器端获取到下一个列表框中的列表信息,再返回浏览器端进行响应显示,下面介绍一下具体的实现过程。
首先在Eclipse中新建一个Web项目,项目名称为P53_DyList,对应的浏览器端页面代码如下:
源文件:dyList.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
</head>
<script language="javascript">
var XMLHttpReq;
//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
//发送请求函数
function sendRequest(url) {
createXMLHttpRequest();
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
}
// 处理返回信息函数
function processResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
updateList();
} else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
// 刷新列表框函数
function refreshList() {
var sort = document.getElementById("sort").value;
if(sort == "" ) {
clearList();
return;
}
var url = "dyList?sort=" + sort;
sendRequest(url)
}
// 更新列表框中列表项函数
function updateList() {
clearList();
var product = document.getElementById("product");
var results = XMLHttpReq.responseXML.getElementsByTagName("name");
var option = null;

for(var i = 0; i < results.length; i++) {
option = document.createElement("option");
option.appendChild(document.createTextNode(results[i].firstChild. nodeValue));
product.appendChild(option);
}
}
// 清除列表框中原有选项的函数
function clearList() {
var product = document.getElementById("product");
while(product.childNodes.length > 0) {
product.removeChild(product.childNodes[0]);
}
}

</script>

<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=2 width=200 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4 colspan="2"><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19 colspan="2"><B>商品搜索</B>
</TD>
</TR>
<tr>
<td height="20">
品牌选择:
</td>
<td height="20">
<select id="sort" onchange="refreshList();">
<option value="default">请选择</option>
<option value="IBM">IBM</option>
<option value="SONY">SONY</option>
<option value="联想">联想</option>
</select>
</td>

</tr>
<tr>
<td height="20">
商品信息:
</td>
<td height="20">
<select id="product" >
</select>
</td>
</tr>

</table>
在该页面中,第一个列表框中提供了对应的品牌选项以供用户进行选择,当用户选择了所需的品牌信息后,将调用“refreshList()”函数,在该函数中首先获取到所选列表项的标志信息,如果用户选择的是“请选择”,则调用“clearList()”函数清除第二个列表框中的内容,如果用户选择的是有效的品牌选项,则借助Ajax提交请求,并同时提交用户所选选项的标识信息到服务器端,等待服务器端的处理。当服务器端后续处理完成后,将返回第二个列表框中的信息,然后在Ajax提供的处理函数中在对应的列表框中显示,在显示时使用了本书第3章中介绍的使用DOM操作HTML的方式。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“dyList”请求时,将由服务器端的类名为“classmate.DyListAction的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.DyListAction</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/dyList</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>dyList.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序DyListAction.java中对应的程序代码。当接收到浏览器端提交的请求后,Servlet程序首先获取浏览器端提交的所选列表项的标志信息,即所选择的商品类别信息,然后借助封装了数据库操作的JavaBean完成数据库的查询工作,依据类别获取到对应的商品名称信息。
package classmate;

import java.io.IOException;
……

public class DyListAction extends HttpServlet {

public void init(ServletConfig config) throws ServletException {
}

/*
* 处理<GET> 请求方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置接收信息的字符集
request.setCharacterEncoding("UTF-8");
//接收浏览器端提交的信息
String sort = request.getParameter("sort");
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");

//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
//查找该品牌具体型号
strSql ="select product.name,product.id from sort,product where sort.id=
product.sortid and sort.name='"+ sort + "'";
rs = db.executeQuery(strSql);
try {
while (rs.next()) {
out.println("<name>" + rs.getString("name") + "</name>");
}
} catch (SQLException e) {
e.printStackTrace();
}

out.println("</response>");
out.close();
}
}
注意在本例中,返回的XML文档的格式如下所示:
<response>
<name>商品名称1</ name>
<name>商品名称2</name>
</response>
读者可以进一步完善该程序,实现从服务器端动态获取第一个列表框中的信息,然后再依据用户选择动态显示第二个列表框中的信息。

实现自动刷新页面
本例实现页面自动刷新的效果,该页面的内容如图5-4所示,在该页面中将根据数据库中存储的最新数据信息更新页面中热卖商品的信息,但是对这些信息的修改并不会导致整个页面的刷新。
实际的Web应用中,诸如:天气预报、直播比赛以及股市行情等页面往往都需要定期进行自动刷新。
传统的Web实现方式中,要想实现类似的效果必须进行整个页面的刷新,在网络速度受到一定限制的情况下,这种因为一个局部变动而牵动整个页面的处理方式显得有些得不偿失。



图5-4 自动刷新页面的效果
借助Ajax技术,可以实现对页面中局部区域的动态刷新,使得用户能够以更好的方式获得最新的数据信息,下面介绍一下自动刷新页面的具体实现过程。
首先在Eclipse中新建一个Web项目,项目名称为P54_AutoRefresh,对应的浏览器端页面代码如下:
源文件:aotuRefresh.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
</head>
<script language="javascript">
var XMLHttpReq;
//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e){
try {
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
//发送请求函数
function sendRequest() {
createXMLHttpRequest();
var url = "refresh";
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
}
// 处理返回信息函数
function processResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
DisplayHot();
setTimeout("sendRequest()", 1000);
} else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
// 显示更新数据信息的函数
function DisplayHot() {
var name = XMLHttpReq.responseXML.getElementsByTagName("name")[0]. firstChild.nodeValue;
var count = XMLHttpReq.responseXML.getElementsByTagName("count")[0]. firstChild.nodeValue;
document.getElementById("product").innerHTML = name;
document.getElementById("count").innerHTML = count;
}

</script>

</SCRIPT>
<body onload =sendRequest()>
<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=0 width=200 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4 colspan="2"><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19 colspan="2"><B>正在热卖的笔记本</B>
</TD>
</TR>
<tr>
<td height="20">
型号:
</td>
<td height="20" id="product">
</td>
</tr>
<tr>
<td height="20">
销售数量:
</td>
<td height="20" id="count">
</td>
</tr>
</body>
</table>
在该页面中在第一次进行页面装载时,将调用“sendRequest()函数,在该函数中将借助Ajax提交请求,等待服务器端的处理。当服务器端后续处理完成后,将返回最新热卖商品的信息,然后在Ajax提供的处理函数中调用“DisplayHot()”函数在页面的对应位置进行显示,在进行显示时使用了本书第3章中介绍的使用DOM操作HTML的方式,同时使用了对应元素的innerHTML属性。此外,为了能够实现页面的自动刷新,在“sendRequest()函数的最后设置了定时器,即在1000ms之后再次调用本函数,执行上面所有的处理工作,从而真正实现页面的自动刷新。注意本例中所使用的setTimeout ("sendRequest()", 1000)函数是HTML DOM中window对象提供的设置定时器的方法。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“refresh”请求时,将由服务器端的类名为classmate.AutoRefreshAction的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.AutoRefreshAction</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/refresh</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>autoRefresh.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序AutoRefreshAction.java中对应的程序代码。当接收到浏览器端提交的请求后,借助封装了数据库操作的JavaBean完成数据库的查询工作,获取最新热卖的商品信息进行响应。
package classmate;

import java.io.IOException;
……

public class AutoRefreshAction extends HttpServlet {

public void init(ServletConfig config) throws ServletException {
}

/*
* 处理<GET> 请求方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");

//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
//查询热卖产品
strSql = "select name,salecount from product order by salecount desc";
rs = db.executeQuery(strSql);
try {
if ( rs.next()) {
out.println("<name>" + rs.getString("name") + "</name>");
out.println("<count>" + rs.getString("salecount") + "</count>");
}
} catch (SQLException e) {
e.printStackTrace();
}

out.println("</response>");
out.close();
}
}
注意在本例中,返回的XML文档的格式如下所示:
<response>
<name>热卖商品名称</ name>
<count>热卖数量</count>
</response>
由于数据库中商品的销售数量一直在发生改变,因此,本例中实现的原则是通过页面自动刷新定期获取数据库中销售数量最高的商品信息,在浏览器端的页面中进行显示。

实现Web页面的局部动态更新
本例中实现的是页面中局部动态更新的效果,对应页面的显示效果如图5-5所示,在该页面中实现的相当于商品信息的后台维护页面,在该页面中用户可以动态增加新的品牌信息到数据库中,增加后的品牌信息将会直接在动态表格中进行显示。同时也可以借助动态表格中的删除按钮进行品牌信息的删除操作。同样在本例中对这些信息的修改并不会导致整个页面的刷新。



图5-5 Web页面的局部刷新效果
传统的Web实现方式中,实现类似的效果必须进行整个页面的刷新。
借助Ajax技术,可以实现对页面中局部区域的动态刷新,使得用户能够以更好的方式获得最新的数据信息,下面介绍一下具体的实现过程。
首先在Eclipse中新建一个Web项目,项目名称为P55_DyUpdate,对应的浏览器端页面代码如下:
源文件:dyUpdate.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<head>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
<LINK href="images/css.css" type=text/css rel=stylesheet>
</head>
<script language="javascript">
var XMLHttpReq;
var PREFIX = "Sort";
//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e){
try {
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
// 处理增加品牌响应函数
function AddStateChange() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
AddSortList();
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
// 增加品牌函数
function addSort() {
name = document.getElementById("name").value;
if(name == "" ) {
return;
}
var url = "dyUpdate?action=add" + "&name="+ name;
createXMLHttpRequest();
XMLHttpReq.onreadystatechange = AddStateChange;
XMLHttpReq.open("GET", url, true);
XMLHttpReq.send(null);
}

function AddSortList() {
var AddID = XMLHttpReq.responseXML.getElementsByTagName("id")[0].firstChild. nodeValue;
if (AddID!=null){
var row = document.createElement("tr");
row.setAttribute("id", PREFIX + AddID);
var cell = document.createElement("td");
cell.appendChild(document.createTextNode(name));
row.appendChild(cell);

var deleteButton = document.createElement("input");
deleteButton.setAttribute("type", "button");
deleteButton.setAttribute("value", "删除");
deleteButton.onclick = function () { deleteSort(AddID); };
cell = document.createElement("td");
cell.appendChild(deleteButton);
row.appendChild(cell);

document.getElementById("sortList").appendChild(row);
//清空输入框
document.getElementById("name").value = "";
}
}

// 删除品牌函数
function deleteSort(id) {
var url = "dyUpdate?action=delete" + "&id=" + id;
createXMLHttpRequest();
XMLHttpReq.onreadystatechange = DeleteStateChange;
XMLHttpReq.open("GET", url, true);
XMLHttpReq.send(null);
}
// 处理删除品牌响应函数
function DeleteStateChange() {
if(XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
deleteSortList();
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}

function deleteSortList() {
deleteID = XMLHttpReq.responseXML.getElementsByTagName("id")[0].firstChild. nodeValue;
if (deleteID!=null){
var rowToDelete = document.getElementById(PREFIX + deleteID);
var sortList = document.getElementById("sortList");
sortList.removeChild(rowToDelete);
}
}

</script>

<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=2 width=400 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4 colspan="3"><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19 colspan="3"><B>品牌信息管理</B>
</TD>
</TR>
<tr>
<td height="20">
增加新品牌:
</td>
<td height="20">
<input id="name" type="text" size="15">
</td>
<td height="20">
<img src="images/ok.gif" onclick="addSort();">
</td>

</tr>
<tr>
<td height="20">
品牌信息管理:
</td>

</tr>
<table border="1" width="400">
<tr>
<td height="20" valign="top" align="center">
品牌名称:
</td>
<td id="pos_1" height="20">
操作
</td>
</tr>
<tbody id="sortList"></tbody>
</table>
</table>
在该页面中当用户在文本框中输入新品牌的名称,单击“提交”按钮后,将调用“addSort()函数,在该函数中首先获取到用户输入的新品牌信息,借助Ajax提交请求,同时提交文本框中用户填写的新的品牌信息,请求的格式为" dyUpdate?action=add" + "&name="+ name可以看到,为了表明请求的类型,使用了参数action,其值为“add”,等待服务器端的处理。当服务器端后续处理完成后,将返回最新的商品品牌信息列表,然后在Ajax提供的处理函数中调用“AddSortList()”函数以动态表格的方式在页面的对应位置进行显示,在进行显示时使用了本书第3章中介绍的使用DOM操作HTML的方式。
此外,当用户在动态表格中选择了对应品牌,单击“操作”按钮后,将调用“deleteSort(),该函数带参数,参数用于传递待操作的品牌标志信息,在“deleteSort()函数中将提交请求,同时提交品牌标志信息到服务器端,请求的格式为"dyUpdate?action=delete" + "&id=" + id可以看到,为了表明请求的类型,使用了参数action,其值为“delete”。等待服务器端的处理。当服务器端后续处理完成后,将调用“deleteSortList()函数借助DOM操作HTML方式从动态表格中去除对应的品牌信息。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“dyUpdate”请求时,将由服务器端的类名为classmate.DyUpdateAction的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.DyUpdateAction</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/dyUpdate</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>dyUpdate.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序DyUpdateAction.java中对应的程序代码。当接收到浏览器端提交的请求后,首先获取请求的类型及相关的数据信息,然后借助封装了数据库操作的JavaBean完成数据库的操作,如果是添加新品牌信息的请求,则向数据库中进行记录插入,否则进行记录删除操作。
package classmate;

import java.io.IOException;
……

public class DyUpdateAction extends HttpServlet {

public void init(ServletConfig config) throws ServletException {
}

/*
* 处理<GET> 请求方法
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置接收信息的字符集
request.setCharacterEncoding("UTF-8");
//接收浏览器端提交的信息
String action = request.getParameter("action");
String name = request.getParameter("name");
String id = request.getParameter("id");
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");

//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
int insRes = 0;
if ("add".equals(action)){
//判断用户名是否重复
strSql = "select max(id) from sort";
rs = db.executeQuery(strSql);
int iMaxId=0;
try {
if ( rs.next()) {
iMaxId=rs.getInt(1)+1;
}
else {
iMaxId=1;
}
} catch (SQLException e) {
e.printStackTrace();
}
if ( iMaxId>0 ){
strSql = "insert into sort values('"
+ iMaxId +"','"
+ name +"')";
insRes = db. executeUpdate(strSql);
}
if(insRes>0){
out.println("<id>" + iMaxId + "</id>");
out.println("<name>" + name + "</name>");
}
}
else if ("delete".equals(action)){
strSql = "delete from sort where id= " + id;
insRes = db. executeUpdate(strSql);
if(insRes>0){
out.println("<id>" + id + "</id>");
}
}
out.println("</response>");
out.close();
}
}
在本例中,完成添加新品牌的请求处理之后,返回的XML文档的格式如下:
<response>
<id>新品牌id</ id>
<name>新品牌名称</name>
</response>
完成品牌删除的请求处理之后,返回的XML文档的格式如下:
<response>
<id>删除品牌id</ id>
</response>

实现自动完成功能
本章实现的最后一个效果如图5-6所示。该页面实现的效果对读者并不陌生,我们在著名的搜索网站Google中已经非常熟悉自动完成功能的效果。本例中当用户在文本框中输入待查询的商品名称时,页面中将根据用户输入的文字信息,及时给出提示列表,以帮助用户快速进行选择,该提示信息来源于服务器端数据库中的数据。当用户选择了对应商品名称,单击“搜索”按钮后,将会在文本区域中显示商品相关的描述信息。
首先在Eclipse中新建一个Web项目,项目名称为P56_AutoComplete,对应的浏览器端页面代码如下:
源文件:autoComplete.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<HTML><HEAD><TITLE>Shopping Online</TITLE>
<META http-equiv=Content-Type content="text/html; charset=UTF-8">
<LINK href="images/css.css" type=text/css rel=stylesheet>



图5-6 自动完成的效果
</HEAD>
<script language="javascript">
var XMLHttpReq;
var completeDiv;
var inputField;
var completeTable;
var completeBody;

//创建XMLHttpRequest对象
function createXMLHttpRequest() {
if(window.XMLHttpRequest) { //Mozilla 浏览器
XMLHttpReq = new XMLHttpRequest();
}
else if (window.ActiveXObject) { // IE浏览器
try {
XMLHttpReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e){
try{
XMLHttpReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
}
//发送匹配请求函数
function findNames() {
inputField = document.getElementById("names");
completeTable = document.getElementById("complete_table");
completeDiv = document.getElementById("popup");
completeBody = document.getElementById("complete_body");
if (inputField.value.length > 0) {
createXMLHttpRequest();
var url = "autoComplete?action=match&names=" + escape(inputField.value);
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processMatchResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
} else {
clearNames();
}
}
// 处理返回匹配信息函数
function processMatchResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
setNames(XMLHttpReq.responseXML.getElementsByTagName("res"));
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}
//生成与输入内容匹配行
function setNames(names) {
clearNames();
var size = names.length;
setOffsets();

var row, cell, txtNode;
for (var i = 0; i < size; i++) {
var nextNode = names[i].firstChild.data;
row = document.createElement("tr");
cell = document.createElement("td");

cell.onmouseout = function() {this.className='mouseOver';};
cell.onmouseover = function() {this.className='mouseOut';};
cell.setAttribute("bgcolor", "#FFFAFA");
cell.setAttribute("border", "0");
cell.onclick = function() { completeField(this); } ;

txtNode = document.createTextNode(nextNode);
cell.appendChild(txtNode);
row.appendChild(cell);
completeBody.appendChild(row);
}
}
//设置显示位置
function setOffsets() {
completeTable.style.width = inputField.offsetWidth; + "px";
var left = calculateOffset(inputField, "offsetLeft");
var top = calculateOffset(inputField, "offsetTop") + inputField. offsetHeight;
completeDiv.style.border = "black 1px solid";
completeDiv.style.left = left + "px";
completeDiv.style.top = top + "px";
}
//计算显示位置
function calculateOffset(field, attr) {
var offset = 0;
while(field) {
offset += field[attr];
field = field.offsetParent;
}
return offset;
}
//填写输入框
function completeField(cell) {
inputField.value = cell.firstChild.nodeValue;
clearNames();
}
//清除自动完成行
function clearNames() {
var ind = completeBody.childNodes.length;
for (var i = ind - 1; i >= 0 ; i--) {
completeBody.removeChild(completeBody.childNodes[i]);
}
completeDiv.style.border = "none";
}
//搜索请求函数
function search() {
var sortName = document.getElementById("names");
createXMLHttpRequest();
var url = "autoComplete?action=search&names=" + escape(inputField.value);
XMLHttpReq.open("GET", url, true);
XMLHttpReq.onreadystatechange = processSearchResponse;//指定响应函数
XMLHttpReq.send(null); // 发送请求
}
// 处理返回匹配信息函数
function processSearchResponse() {
if (XMLHttpReq.readyState == 4) { // 判断对象状态
if (XMLHttpReq.status == 200) { // 信息已经成功返回,开始处理信息
var res=XMLHttpReq.responseXML.getElementsByTagName("res");
if (res.length>0){
document.getElementById("content").value=res[0].firstChild.data;
}
}else { //页面不正常
window.alert("您所请求的页面有异常。");
}
}
}

</script>

<table style="BORDER-COLLAPSE: collapse" borderColor=#111111
cellSpacing=0 cellPadding=2 width=400 bgColor=#f5efe7 border=0>
<TR>
<TD align=middle height=4 colspan="3"><IMG height=4
src="images/promo_list_top.gif" width="100%"
border=0>
</TD>
</TR>
<TR>
<TD align=middle bgColor=#dbc2b0
height=19 colspan="3"><B>商品信息搜索</B>
</TD>
</TR>
<tr>
<td height="20">
输入品牌关键字:
</td>
<td height="20">
<input type="text" size="15" id="names" onkeyup="findNames();" style=
"height:20;">
<div style="position:absolute;" id="popup">
<table id="complete_table" bgcolor="#FFFAFA" border="0" cellspacing=
"0" cellpadding="0"/>
<tbody id="complete_body"></tbody>
</table>
</div>
</td>

<td height="20">
<img src="images/search.gif" onclick="search();">
</td>

</tr>
<tr>
<td height="20" valign="top" align="center">
产品描述:
</td>
<td id="pos_1" height="80">
<textarea id="content">

</textarea>
</td>
</tr>

</table>
在该页面中一旦用户开始在文本框中输入待查询商品的名称,即触发“onkeyup”事件,调用“findNames()函数,在该函数中首先获取到用户已经在文本框中输入的信息,然后借助Ajax提交请求,同时提交文本框中用户已经填写的信息,请求的格式为" autoComplete? action=match&names=" + escape(inputField.value)可以看到,为了表明请求的类型,使用了参数action,其值为“match”,等待服务器端的处理。当服务器端后续处理完成后,将返回获取到的与用户已输入信息相匹配的信息列表,在Ajax提供的处理函数中调用“setNames(names)”函数以动态方式在页面的对应位置进行显示,在进行显示时还调用了“setOffsets()”函数以及“calculateOffsets()”函数。
此外,当用户录入完待查询的商品名称,单击“搜索”按钮后,将调用“search(),该函数将首先获取待查询的商品名称信息,然后提交请求,同时提交待查询商品信息到服务器端,请求的格式为" autoComplete?action=search&names=" + escape(inputField.value)可以看到,为了表明请求的类型,使用了参数action,其值为“search”。等待服务器端的处理。当服务器端后续处理完成后,将调用“processSearchResponse()函数在对应的文本区域中显示查询的商品描述信息。
该Web应用的配置文件web.xml对应的代码如下所示。从该配置文件中可以了解到,当浏览器端提交“autoComplete”请求时,将由服务器端的类名为classmate.AutoCompleteAction的Servlet程序进行处理。
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>ms1</servlet-name>
<servlet-class>classmate.AutoCompleteAction</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>ms1</servlet-name>
<url-pattern>/autoComplete</url-pattern>
</servlet-mapping>

<!-- The Welcome File List -->
<welcome-file-list>
<welcome-file>autoComplete.jsp</welcome-file>
</welcome-file-list>
</web-app>
下面我们关注一下服务器端Servlet程序AutoCompleteAction.java中对应的程序代码。当接收到浏览器端提交的请求后,首先获取请求的类型及相关的数据信息,然后借助封装了数据库操作的JavaBean完成数据库的操作,例如:获取候选商品名称信息,或者查询指定商品的描述信息等。
package classmate;

import java.io.IOException;
……
public class AutoCompleteAction extends HttpServlet {

public void init(ServletConfig config) throws ServletException {
}

……
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//设置接收信息的字符集
request.setCharacterEncoding("UTF-8");
//接收浏览器端提交的信息
String action = request.getParameter("action");
String name = request.getParameter("names");
//设置输出信息的格式及字符集
response.setContentType("text/xml; charset=UTF-8");
response.setHeader("Cache-Control", "no-cache");
//创建输出流对象
PrintWriter out = response.getWriter();
//依据验证结果输出不同的数据信息
out.println("<response>");

//数据库操作
DB db = new DB();
ResultSet rs;
String strSql=null;
//匹配
if ("match".equals(action)){
strSql = "select * from product where name like'" + name + "%'";
rs = db.executeQuery(strSql);
try {
while(rs.next()) {
out.println("<res>" + rs.getString("name") + "</res>");
}
}catch (SQLException e) {
e.printStackTrace();
}
}
else if ("search".equals(action)){
strSql = "select contents from product where name ='" + name + "'";
rs = db.executeQuery(strSql);
try {
if ( rs.next()) {
out.println("<res>" + rs.getString("contents") + "</res>");
}
}catch (SQLException e) {
e.printStackTrace();
}

}
out.println("</response>");
out.close();
}
}
在本例中,完成match类型的请求处理之后,返回的XML文档的格式如下所示:
<response>
<res>候选商品名称1</ res>
<res>候选商品名称1</ res>
<res>候选商品名称1</ res>
</response>
完成search类型的请求处理之后,返回的XML文档的格式如下所示:
<response>
<res>商品描述信息</ res>
</response>
至此,本章相关的案例介绍完毕,通过本章的学习,读者对Ajax的实际应用方式和技巧都应有了一定程度的掌握和理解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: