Ajax - 基础教程第八章例子学习五

原创 2007年09月11日 17:56:00

新闻搜索版块 

 老规矩,先贴下web service的地址:http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=thunderboltsoft&zip=94306&results=10&query=ajax

 这个版块不像前面的自动填充那个,这个是通过你输入的关键字,然后帮你查找新闻,在把这些新闻填充到下面的DIV中。

一。 主界面search.jsp

代码清单8-18 search.jsp

<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 

<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 id="popup" style="position:absolute;overflow:auto;display:none;background-color:white" >
    
</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>
        
<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

package ajaxdashboard.servlet;

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://java.sun.com/jsp/jstl/core" prefix="c"%> 
<%@ 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);">
                
<href="${result.url}" class="autocomplete" target="_blank">
                    ${result.title}
                
</a>
            
</div>
        
</c:forEach>
                       
    
</tac:replaceChildren>
    
</tac:taconiteRoot>

taconite框架,没什么好说的,建议大家去看看taconite框架中的例子,可以学到很多taconite框架的用法,这些都很实用的。

到这里,ajax基础教程第八章的例子,在经过查找错误,改正,对一些地方改良以后,终于完成了,运行你的例子看看吧

《Objective-C基础教程》学习笔记第八章

1. Fundation kit中一些有用的数据类型:常用结构体:NSRange, NSPoint, NSSize, NSRect; 常用类: NSString, NSMutableString, N...
  • guiding
  • guiding
  • 2013年02月05日 18:28
  • 361

笔记:《高效能人士的七个习惯》第八章 习惯五 知彼解己——移情沟通的原则

1、若要用一句话归纳我在人际关系方面学到的一个最重要的原则,那就是:知彼解己——首先寻求去了解对方,然后再争取让对方了解自己。这一原则是进行有效人际交流的关键。 2、心灵世界自有其理,非理智所能企及...
  • icamera0
  • icamera0
  • 2016年01月19日 21:51
  • 1357

jQuery基础教程第八章学习

构建功能型表单 刚开始看代码就发现了一个从来没见过的标签,,这个标签是专门用来修饰表单元素的,当表单在这个标签里面时,浏览器就会以特殊的方式来显示它们,它们可能有特殊的边界之类的。 .en...
  • u012248889
  • u012248889
  • 2013年11月06日 23:53
  • 352

Ajax学习(二)—— 一个简单的Ajax实例

通过上篇博客认识Ajax之后,我们通过一个简单的实例来消化消化理论知识,一睹Ajax的庐山真面目。 1.实例功能: 当用户输入用户名,文本框失去焦点后,通过异步调用来判断该用户名是否已经存在。若存...
  • CYL_happygirl
  • CYL_happygirl
  • 2014年11月07日 21:20
  • 13089

《Python基础教程》第6~8章 学习笔记

《Python基础教程》 学习笔记 第二弹,6-8章。markdown排版。
  • hcbbt
  • hcbbt
  • 2014年01月26日 17:44
  • 2232

Java语言程序设计基础篇 第八章 课后编程答案

import java.util.Scanner; public class ch0801{ public static void main( String[] args ){ Rectang...
  • u010717079
  • u010717079
  • 2014年04月06日 13:33
  • 5123

JS中ajax学习基础教程

当接触一项新技术时,首先我们要问自己四个问题,如果这四个问题我们都能学习并理解到位,那么可以说这个新技术你已经完成了初步掌握,下面我们就这四个问题来说ajax应该怎么学习。 一,ajax是什...
  • v_111
  • v_111
  • 2017年05月02日 13:07
  • 293

jquery+ajax简单的例子

ajax test jQuery(function($){ $('button').click(function(){ var name = $(this).attr('name');...
  • xluren
  • xluren
  • 2013年11月29日 10:46
  • 7868

第 1 章 开始学习 CSS,为网页添加样式

认识 CSS 样式 CSS 代码语法 CSS 注释代码 认识 CSS 样式CSS 全称为“层叠样式表 (Cascading Style Sheets)”,它主要是用于定义 HTML 内容在浏览器内的显...
  • lgy64422575
  • lgy64422575
  • 2016年01月26日 15:46
  • 205

机器学习实战 第八章 预测数值型数据:回归(Regression)

首先介绍线性回归,然后引入局部平滑技术,更好地拟合数据。接着探讨回归在“欠拟合”情况下的缩减(shrinkage),探讨偏差和方差的概念。用线性回归找到最佳拟合直线优点:结果已于理解,计算上并不复杂。...
  • namelessml
  • namelessml
  • 2016年09月16日 12:11
  • 1745
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Ajax - 基础教程第八章例子学习五
举报原因:
原因补充:

(最多只允许输入30个字)