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

新闻搜索版块 

 老规矩,先贴下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" οnfοcus="onFocusFunction('searchTerm');"/>中的οnfοcus="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" οnfοcus="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基础教程第八章的例子,在经过查找错误,改正,对一些地方改良以后,终于完成了,运行你的例子看看吧

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
AJAX (Asynchronous JavaScript and XML) 是一种用于前后端数据交互的技术。它允许在不刷新整个页面的情况下,通过异步方式向服务器发送请求并获取响应数据。 使用 AJAX 可以实现以下功能: 1. 发送异步请求:通过 JavaScript 创建 XMLHttpRequest 对象,并使用该对象发送 HTTP 请求到服务器。 2. 处理响应数据:一旦服务器返回响应,可以通过回调函数处理返回的数据。常见的数据格式包括 XML、JSON 或纯文本。 3. 更新页面内容:根据服务器返回的数据,可以使用 JavaScript 动态更新页面内容,而不需要刷新整个页面。这样可以提升用户体验并减少网络流量。 以下是一个简单的 AJAX 示例代码: ```javascript // 创建 XMLHttpRequest 对象 var xhr = new XMLHttpRequest(); // 指定请求的方法和 URL xhr.open('GET', 'https://api.example.com/data', true); // 设置回调函数处理响应 xhr.onreadystatechange = function() { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { // 处理服务器返回的数据 var response = xhr.responseText; console.log(response); // 更新页面内容 document.getElementById('result').innerHTML = response; } }; // 发送请求 xhr.send(); ``` 在上述示例中,我们使用 AJAX 发送了一个 GET 请求到 `https://api.example.com/data`,并设置了一个回调函数来处理服务器返回的数据。在回调函数中,我们将返回的数据打印到控制台,并将其更新到 id 为 `result` 的 HTML 元素中。 通过 AJAX,前端可以与后端进行实时的数据交互,从而实现更加动态和响应式的用户界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值