Ajax - 基础教程第八章例子学习五
来源:互联网 发布:c#多线程编程实例 pdf 编辑:程序博客网 时间:2024/06/07 02:18
新闻搜索版块
老规矩,先贴下web service的地址:http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=thunderboltsoft&zip=94306&results=10&query=ajax
这个版块不像前面的自动填充那个,这个是通过你输入的关键字,然后帮你查找新闻,在把这些新闻填充到下面的DIV中。
一。 主界面search.jsp
代码清单8-18 search.jsp
<div id="searchRoot" style="left:500px; top:450px;">
<div id="searchHandle">
<table width="100%" border="0" class="textbox">
<tr>
<td align="left" class="controls">
Search Powered by Yahoo!
</td>
</tr>
</table>
</div>
<div id="searchContent" class="searchContent">
Search term: <input class="normalText" type="text" name="searchTerm" id="searchTerm" onfocus="onFocusFunction('searchTerm');"/>
<br/>
</div>
</div>
下面的搜索填充框是在ajaxDashboard.jsp中
</div>
二。 ajaxDashboard.js在页面加载是运行函数initDomDrag("searchHandle", "searchRoot");这是鼠标拖动方法,但可惜的是新闻填充的DIV是在searchRoot的外面,所以拖动的话是会跟填充框脱离的,感觉这个版块的作者跟前面的版块的作者很大区别,特别是写的js,又长有难读懂。
加载页面时,ajaxDashboard.js运行了方法
AutocompleteManager.registerHandler(new AutocompleteHandler("searchTerm", "Search", 275, 3));
这个方法的定义是在autocomplete.js中,
var AutocompleteManager = new AutocompleteManagerImpl();
AutocompleteManager是函数AutocompleteManagerImpl()的一个对象。
function AutocompleteManagerImpl() {
this.textboxes = new Object();
............................................
this.registerHandler = function(handler) {
this.textboxes[handler.id] = handler;
}
}
这个AutocompleteManager对象的初始化是通过一个Object对象textboxes保存一个AutocompleteHandler(id, url, interval, minLength) 对象,调用这个textboxes很简单,就是知道id就行了,在这个例子中,AutocompleteManager.textboxes[ searchTerm ]就能得到这个对象了,反正id是固定的,所以这个不用想太多了。
function AutocompleteHandler(id, url, interval, minLength) {
this.id = id; //标识对象的id标志
this.url = url; //用到的Servlet
this.interval = interval; //循环定时器的设定时间
this.minLength = minLength; //查询字符串最少的字节
this.lastSearchString = "";
this.timeoutID; //循环定时器开关
this.state = "stopped"; //状态
}
启动Ajax的是<input class="normalText" type="text" name="searchTerm" id="searchTerm" onfocus="onFocusFunction('searchTerm');"/>中的onfocus="onFocusFunction('searchTerm');"
我不明白作者为什么用onfocus,其实用onchange跟onkeyup这些应该也可以的,这些先不管啦,看看
function onFocusFunction(id) {
AutocompleteManager.startTheInterval(id);
}
this.startTheInterval = function(id) {
var handler = this.textboxes[id]; //取得AutocompleteHandler对象,主要是要它里面的属性状态
if(handler.state == "running") { //如果在上一次启动AJAX没完成,handler.state是running的,防止多次启动AJAX服务
return;
}
var functionString = "handleInterval('" + id + "');" ;
handler.timeoutID = window.setInterval(functionString, handler.interval); //其实这个是用一次就行了,可以用一次定时器setTimeout,而不是用循环定时器setInterval,虽然用了searchString == handler.lastSearchString的判断使Ajax服务不会重复执行,但用一次定时器setTimeout就不用加多这些东西了,也不用加多定时器开关了
handler.state = "running";
}
这个方法中,主要是启动了函数function handleInterval(id) ,
function handleInterval(id) {
var searchString = document.getElementById(id).value; //取得输入框的值
var handler = AutocompleteManager.getHandlerFor(id); //取得AutocompleteHandler对象
if(searchString.length < handler.minLength || searchString.length == 0) {//输入值长度为0或小于规定最小长度
clearPopup(); //清除popupDIV
hideAutoComplete(); //隐藏popupDIV,这两个函数很简单,就不列出了
return;
}
if(searchString == handler.lastSearchString) {//跟上次输入字符串比较,防止重复启动AJAX服务
return;
}
//Made it this far so make the request一切ok,启动AJAX服务
doRequest(id, handler.url);
//Remember the last search string保存这次输入字符串
handler.lastSearchString = document.getElementById(id).value;
}
doRequest方法
function doRequest(textboxID, url) {
setOffsets(textboxID); //这个主要是设置popupDIV的偏移量跟输入框能一致,代码是一样的,所以不贴出来
var textbox = document.getElementById(textboxID);
if(textbox.value.length > 1) { //taconite框架,没什么好讲的啦
var ajaxRequest = new AjaxRequest(url);
ajaxRequest.addNamedFormElements(textboxID);
ajaxRequest.setPostRequest(showPopup);
ajaxRequest.sendRequest();
}
else if(textbox.value.length == 0) {
clearPopup(); //清除popupDIV的内容,并设置为隐藏
}
}
function showPopup(ajaxRequest) { //设置popupDIV为显示状态
document.getElementById("popup").style.display = "";
}
js方面的主要过程就是这样啦
如果你想让popupDIV能一起随着鼠标拖动,那要注意我这里给出的修改方法了
首先把ajaxDashboard.jsp中的
<div id="popup" style="position:absolute;overflow:auto;display:none;background-color:white" >
</div>
放到search.jsp中的searchContentDIV下面,像这样
<div id="searchContent" class="searchContent">
Search term: <input class="normalText" type="text" name="searchTerm" id="searchTerm" onfocus="onFocusFunction('searchTerm');"/>
<br/>
</div>
<div id="popup" style="position:absolute;overflow:auto;display:none;background-color:white" >
</div>
然后在autocomplete.js中的函数function setOffsets(textboxID)中的
popup.style.left = 76 + "px";
popup.style.top = 47 + "px";
设置数字是经过本人的反复试验出来的,使popupDIV能跟输入框的偏移量一致,因为popuoDIV放在searchRootDIV中,所以也能跟着随鼠标拖动
三。 SearchServlet.java,在AJAX服务中用到的servlet
在web.xml中添加
<servlet-name>SearchServlet</servlet-name>
<servlet-class>ajaxdashboard.servlet.SearchServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SearchServlet</servlet-name>
<url-pattern>/Search</url-pattern>
</servlet-mapping>
代码清单8-19 SearchServlet.java
import ajaxdashboard.service.SearchService;
import java.io.*;
import java.util.Collection;
import javax.servlet.*;
import javax.servlet.http.*;
public class SearchServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 3137159287689087514L;
private static final String AJAX_JSP = "/search/searchAutocomplete.jsp";
protected void processRequest(HttpServletRequest request
, HttpServletResponse response)
throws ServletException, IOException {
String searchTerm = request.getParameter("searchTerm");
System.out.println(" ==========Searching: " + searchTerm);
SearchService searchService = new SearchService();
Collection results = searchService.search(searchTerm);
// for(Iterator it = results.iterator(); it.hasNext();) {
// System.out.println(((SearchResult)it.next()).toString());
// }
request.setAttribute("results", results);
request.getRequestDispatcher(AJAX_JSP).forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
}
跟前面几个版块一样,SearchServlet中的数据的取得主要是用到了SearchService.java,Collection results = searchService.search(searchTerm);再把results放到request变量中,传递到taconite框架页面上
代码清单8-20 SearchService.java
package ajaxdashboard.service;
import ajaxdashboard.domain.SearchResult;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
/**
*
* @author Owner
*/
public class SearchService {
private static final String YAHOO_SEARCH_URL =
"http://local.yahooapis.com/LocalSearchService/V3/localSearch"
+ "?appid=thunderboltsoftware"
+ "&zip=94306"
+ "&results=10"
+ "&query=";
private InputStream getResultsInputStream(String searchTerm) throws Exception {
String url = YAHOO_SEARCH_URL + searchTerm;
System.out.println("url: " + url);
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection();
con.setDoInput(true);
con.setDoOutput(true);
con.setRequestMethod("GET");
return con.getInputStream();
}
public Collection search(String searchTerm) {
Document resultsXML = getSearchResultsXML(searchTerm);
return parseResults(resultsXML);
}
private Document getSearchResultsXML(String searchTerm) {
SAXBuilder builder = new SAXBuilder();
Document news = null;
try {
InputStream searchResultsInputStream = getResultsInputStream(searchTerm);
news = builder.build(searchResultsInputStream);
}
catch (JDOMException ex) {
System.out.println("Error: " + ex.toString());
}
catch (IOException ex) {
System.out.println("Error: " + ex.toString());
}
catch(Exception ex) {
System.out.println("Exception: " + ex.toString());
}
return news;
}
private Collection parseResults(Document results) {
Collection searchResults = new ArrayList();
Namespace ns = Namespace.getNamespace("urn:yahoo:lcl");
Element root = results.getRootElement();
List items = root.getChildren("Result", ns);
System.out.println("res size: " + items.size());
Element item = null;
SearchResult result = null;
for(Iterator it = items.iterator(); it.hasNext();) {
item = (Element)it.next();
result = new SearchResult();
result.setTitle(item.getChildText("Title", ns));
result.setAddress(item.getChildText("Address", ns));
result.setUrl(item.getChildText("Url", ns));
searchResults.add(result);
}
return searchResults;
}
}
其实理清整个过程,理解起来很简单的,这个跟新闻标题版块一样是通过链接获取服务的,所以先确定URL,下面的步骤基本都是一样的啦
HttpURLConnection con = (HttpURLConnection)new URL(url).openConnection(); //打开连接
con.setDoInput(true); //设置连接输入功能
con.setDoOutput(true); //设置连接输出功能
con.setRequestMethod("GET"); //设置请求方式,get或post或其他的
InputStream searchResultsInputStream = con.getInputStream(); //确定连接输入数据
SAXBuilder builder = new SAXBuilder();
Document news = null;
news = builder.build(searchResultsInputStream); //用SAXBuilder对象把输入的数据转换成一定格式的文档,这里我的理解是xml文档。
//可能是用org.jdom.input.SAXBuilder转换的,所以有命名空间的话,命名空间要设置
Namespace ns = Namespace.getNamespace("urn:yahoo:lcl"); //注意这里,这个是修改过的了,源代码中用到的是错误的
Element root = results.getRootElement(); //这个是固定的,取得xml文档的root元素
List items = root.getChildren("Result", ns); //取得标记名为<Result>的子元素的数组items
for(Iterator it = items.iterator(); it.hasNext();) { //取得子元素数组items中的元素
item = (Element)it.next(); //items中的元素
item.getAttribute("id", ns) //取得该元素的某个属性值
item.getChildText("Title",ns) //取得该元素的子元素的值(前提是该子元素已经没子元素了)
}
这里用到的jdom.jar
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
//然后你可以把这些数据放到实体类的集合中,再把这个集合保存到request变量中
//像新闻标题版块那个web service是没命名空间的,所以直接用List items = root.getChildren("Result");把ns去掉就行了
四。 searchAutocomplete.jsp
代码清单8-21 searchAutocomplete.jsp
<%@ taglib uri="http://taconite.sf.net/tags" prefix="tac" %>
<tac:taconiteRoot>
<tac:replaceChildren contextNodeID="popup" parseOnServer="true">
<c:forEach var="result" items="${results}">
<div onmouseover="hilite(this);" onmouseout="unhilite(this);">
<a href="${result.url}" class="autocomplete" target="_blank">
${result.title}
</a>
</div>
</c:forEach>
</tac:replaceChildren>
</tac:taconiteRoot>
taconite框架,没什么好说的,建议大家去看看taconite框架中的例子,可以学到很多taconite框架的用法,这些都很实用的。
到这里,ajax基础教程第八章的例子,在经过查找错误,改正,对一些地方改良以后,终于完成了,运行你的例子看看吧
- Ajax - 基础教程第八章例子学习五
- Ajax - 基础教程第八章例子学习一
- Ajax - 基础教程第八章例子学习二
- Ajax - 基础教程第八章例子学习三
- Ajax - 基础教程第八章例子学习四
- jQuery基础教程第八章学习
- 《Objective-C基础教程》学习笔记第八章
- 《Ajax基础教程》学习笔记---第2章
- 学习《Ajax基础教程》点滴
- Python基础教程第八章学习笔记——异常
- python基础教程学习笔记五
- Ajax基础教程整理,学习笔记
- JS中ajax学习基础教程
- Access基础教程--第八章 使用VBA编程
- jquery基础教程的第八章-购物che
- Objective-C基础教程(第一版)-学习笔记第八章Foundation Kit快速教程
- [学习笔记—Objective-C]《Objective-C-基础教程 第2版》第八章 Foudation Kit 介绍
- AJAX学习小例子
- asp.net 邮件发送 将一个网页的内容作邮件的内容发送
- JAVASCRIPT函数库(上)
- grails 命令使用
- JAVASCRIPT函数库(下)
- 十分钟让你懂得中国经济(转载)
- Ajax - 基础教程第八章例子学习五
- JavaScript:prototype属性使用说明
- js关于document和window对象
- 网页数据抓取并分析
- 计算机图形学教学大纲
- 再探跳马问题(骑士周游问题)
- JavaScript实用的一些技巧
- 使用JDesktop Integration Components实现桌面系统托盘
- 为Url地址页面制作一个桌面快捷方式