Dedian  
          -- 關(guān)注搜索引擎的開發(fā)
          日歷
          <2006年10月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234
          統(tǒng)計(jì)
          • 隨筆 - 82
          • 文章 - 2
          • 評(píng)論 - 228
          • 引用 - 0

          導(dǎo)航

          常用鏈接

          留言簿(8)

          隨筆分類(45)

          隨筆檔案(82)

          文章檔案(2)

          Java Spaces

          搜索

          •  

          積分與排名

          • 積分 - 65547
          • 排名 - 817

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

           

          ---祝大家中秋愉快---

          Ajax (AsynchronousJavaScript and XML)是近年來流行的一門web 技術(shù)。在Blogjava上看到有人開始在介紹AJAX,但仿佛流于概念或理論的東西,對于想用Ajax的初學(xué)者似乎不是很make sense。我想,學(xué)習(xí)任何一樣新的技術(shù),例子和步驟是極為make sense的兩樣?xùn)|西。

          筆者想結(jié)合過去的學(xué)習(xí)經(jīng)驗(yàn)簡單講講使用Ajax的基本步驟和舉幾個(gè)實(shí)用例子。由于筆者主要在于后臺(tái)端的開發(fā),所以很多腳本并不是很擅長。Ajax也主要限于以前大學(xué)的修課和近期的一些為后臺(tái)端程序的測試的簡單實(shí)現(xiàn)。所以只是一個(gè)拋磚引玉的使用Ajax版本,歡迎相互學(xué)習(xí)交流。

          0. 導(dǎo)讀

          ??? 1。使用Ajax的基本流程
          ???
          2。使用Ajax的基本步驟。(簡單例子--> Demo)
          ??? 3。
          再來一個(gè)例子(Google Suggest)。(Demo)
          ??? 4。家庭作業(yè) :)


          1。使用Ajax的基本流程

          在筆者看來,Ajax更像是一個(gè)簡單的網(wǎng)絡(luò)框架,它描述著如何高效地使網(wǎng)絡(luò)前端的數(shù)據(jù)展現(xiàn)和網(wǎng)絡(luò)后端的數(shù)據(jù)之間的交互?;旧?,就是瀏覽器提供一個(gè)XMLHttpRequest(當(dāng)然在IE里是ActiveXObject)的對象向后臺(tái)端的腳本程序或者Servlet Classes發(fā)送http請求,從后臺(tái)端的回應(yīng)中獲取文本數(shù)據(jù)(如xml格式和最近有人討論的Json格式)并嵌入前臺(tái)段的網(wǎng)頁中或腳本中。

          下圖是一個(gè)簡單的流程圖:



          2。使用Ajax的基本步驟。

          下面,我們結(jié)合上面的流程,以及一個(gè)簡單的例子(見這篇文章)過一遍基本的步驟。(藍(lán)色代碼為標(biāo)準(zhǔn)寫法)

          第一步:Form 代碼:接受前臺(tái)端的輸入,并通過Action方法(方法函數(shù)里包含創(chuàng)建XMLHttpRequest對象)把request post到后臺(tái)端。

          <input id="username" name="username" type="text"
          ? onblur="checkName(this.value,'')" />
          <span class="hidden" id="nameCheckFailed">
          ? This name is in use, please try another.
          </span>

          <script language="javascript">
          function checkName(input, response)
          {
          ? if (response != ''){
          ??? // Response mode
          ??? message?? = document.getElementById('nameCheckFailed');
          ??? if (response == '1'){
          ????? message.className = 'error';
          ??? }else{
          ????? message.className = 'hidden';
          ??? }
          ? }else{
          ??? // Input mode
          ??? url? = 'http://localhost/xml/checkUserName.php?q=' + input;
          ??? loadXMLDoc(url);
          ? }
          }

          var req;

          function loadXMLDoc(url)
          {
          ??? // branch for native XMLHttpRequest object
          ??? if (window.XMLHttpRequest) {
          ??????? req = new XMLHttpRequest();
          ??????? req.onreadystatechange = processReqChange;
          ??????? req.open("GET", url, true);
          ??????? req.send(null);
          ??? // branch for IE/Windows ActiveX version
          ??? } else if (window.ActiveXObject) {
          ??????? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??????? if (req) {
          ??????????? req.onreadystatechange = processReqChange;
          ??????????? req.open("GET", url, true);
          ??????????? req.send();
          ??????? }
          ??? }
          }
          </script>


          注:
          1。 這里的form只是一個(gè)input box,action的方法是onblur,就是響應(yīng)失去焦點(diǎn)的事件,然后調(diào)用一個(gè)函數(shù)checkName, 這個(gè)函數(shù)里通過XMLHttpRequest向PHP server script 發(fā)送Post請求(看得出來,這里的php server script的文件名叫checkUserName.php,唯一參數(shù)是q)。
          2。函數(shù)loadXMLDoc里有個(gè)通用的創(chuàng)建XMLHttpRequest對象的代碼,標(biāo)準(zhǔn)代碼整理如下:
          ??????? var req;
          ??? ??? function foo()
          ??? ??? {
          ??? ??? ??? req = false;

          ??? ??? ??? // branch for native XMLHttpRequest object
          ??? ??? ??? if(window.XMLHttpRequest)
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new XMLHttpRequest();
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? try
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? if(req)
          ??? ??? ??? {
          ??? ?? ?? ?? ?? ??
          //do something here
          ???? ??? ??? }
          ??? ??? ???

          ??? ??? }

          第二步:響應(yīng)文本處理代碼:XMLHttpRequest對象里有個(gè)類似消息響應(yīng)函數(shù)的屬性,即通過設(shè)置 req.onreadystatechange 來告訴XMLHttpRequest在哪個(gè)函數(shù)里處理服務(wù)端返回的文本信息。
          如在上面的例子中:
          req.onreadystatechange = processReqChange;
          那么我們接著要有一個(gè)processReqChange的函數(shù):
          function processReqChange() 
          {
          // only if req shows "complete"
          if (req.readyState == 4) {
          // only if "OK"
          if (req.status == 200)
          {
          // ...processing statements go here...
          processResponse();
          } else {
          alert("There was a problem retrieving
          the XML data:\n" + req.statusText);
          }
          }
          }


          function processResponse()
          {
          response = req.responseXML.documentElement;
          method = response.getElementsByTagName('method')[0].firstChild.data;
          result = response.getElementsByTagName('result')[0].firstChild.data;
          eval(method + '(\'\', result)');

          }
          注:
          1。 基本上processReqChange 函數(shù)是標(biāo)準(zhǔn)代碼的寫法。
          2。這里要用到前面定義的全局變量(XMLHttpRequest對象)req

          第三步:后臺(tái)端代碼(這個(gè)例子是php server script):接受前臺(tái)端的請求,處理其參數(shù),并返回相應(yīng)的結(jié)果。

          文件名: checkUserName.php

          <?php
          header('Content-Type: text/xml');

          function nameInUse($q)
          {?
          ? if (isset($q)){
          ??? switch(strtolower($q))
          ??? {
          ????? case? 'drew' :
          ????????? return '1';
          ????????? break;
          ????? case? 'fred' :
          ????????? return '1';
          ????????? break;
          ????? default:
          ????????? return '0';
          ??? }
          ? }else{
          ??? return '0';
          ? }
          ?
          }
          ?>
          <?php echo '<?xml version="1.0" encoding="UTF-8"? standalone="yes"?>'; ?>
          <response>
          ? <method>checkName</method>
          ? <result><?php
          ??? echo nameInUse($_GET['q']) ?>
          ? </result>
          </response>
          注:代碼很簡單,就不用解釋了。這里返回的是xml格式的字符串。

          總體效果見這里
          輸入"fred"或者"drew"的名字,失去焦點(diǎn)后會(huì)顯示名字已存在的信息。


          ?3。再來一個(gè)例子。

          這里再講一個(gè)實(shí)用的例子,這是以前上課的一個(gè)課堂作業(yè),也很有代表性。是關(guān)于Google Suggest(好像新的Google Toolbar上就用的這個(gè)功能)的應(yīng)用問題。這里是寫好的DEMO。現(xiàn)在越來越多的網(wǎng)站提供類似Web Service的API, 我們利用他們提供的API URL可以返回一些我們用的著的數(shù)據(jù),放在我們的網(wǎng)頁上。這里就用的上Ajax。只不過有些返回來的文本數(shù)據(jù)是xml格式的,就可以利用上面的簡單例子來處理,但很多像Google Suggest那樣是返回一段類似代碼格式的文本。我們就要利用Javascript的eval函數(shù),把這些文本當(dāng)作一段代碼在嵌入自己的網(wǎng)頁中。如果嵌入的代碼中含有函數(shù),則需要自己再寫一個(gè)同名的函數(shù)作為實(shí)現(xiàn)。(這就是流程圖中的optional的func 3)

          這里完整代碼就不貼了,貼一些關(guān)鍵代碼(原本后臺(tái)端是用Java Servlet寫的,但做demo的空間沒有Tomcat不支持Servlet,所以改用Php實(shí)現(xiàn),大家可以自己用Java再寫一邊作為家庭作業(yè) :) ):

          1) form 代碼:

          <form name = "QForm" method="POST" action="google_suggest.php">
          ??? <table bgcolor="8080C0" width="90%" >
          ??? <tr>
          ??? ??? <td? nowrap>Search Term:</td>
          ??? ??? <td ><input type="text" name="qtext"? onkeyup="return GetSuggestion()" size="60"></td>
          ??? </tr>
          ??? <tr>
          ??? ??? <th colspan="2" align="left" bgcolor="#A8A8FF"><DIV id=google_suggest_target>results go here . . . </DIV></th>
          ??? </tr>
          ??? </table>
          ??? </form>

          注:
          a. 看得出來,要把查詢的字符串post到google_suggest.php上
          b. action的函數(shù)是GetSuggestion(),其返回的字符串會(huì)顯示在預(yù)留的網(wǎng)頁空間里。

          2) 后臺(tái)端代碼(PHP):這里主要接收前臺(tái)的請求,并不請求轉(zhuǎn)化為向Google Suggest的API URL請求,把接收到的文本信息返回給前端。代碼很簡單,如下:

          文件名:google_suggest.php

          <?php
          function getGoogleSuggest($q)
          {

          ??? $url = "http://www.google.com/complete/search?hl=en&js=true&qu=" . $q;
          ??? return file_get_contents($url);
          }
          ?>

          <?php echo getGoogleSuggest($_POST['q']) ?>

          注:
          a。 Google Suggest API 返回的是一個(gè)代碼格式的文本信息,如下:
          sendRPCDone(frameElement, "", new Array(), new Array(), new Array(""));
          所以我們再前臺(tái)接受到這個(gè)文本信息之后,應(yīng)該寫一個(gè)sendRPCDone的函數(shù)來做進(jìn)一步信息處理(比如說列表出查詢結(jié)果)。

          3) 前臺(tái)文本處理代碼:

          ??? <script type="text/javascript">
          ??? ??? var req;
          ??? ??? function GetSuggestion()
          ??? ??? {
          ??? ??? ??? req = false;
          ??? ??? ??? var f = document.QForm;

          ??? ??? ??? // branch for native XMLHttpRequest object
          ??? ??? ??? if(window.XMLHttpRequest)
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new XMLHttpRequest();
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? else if(window.ActiveXObject) // branch for IE/Windows ActiveX version
          ??? ??? ??? {
          ??? ??? ??? ??? try
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? req = new ActiveXObject("Msxml2.XMLHTTP");
          ??? ??? ??? ??? }
          ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? try
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = new ActiveXObject("Microsoft.XMLHTTP");
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? ??? catch(e)
          ??? ??? ??? ??? ??? {
          ??? ??? ??? ??? ??? ??? req = false;
          ??? ??? ??? ??? ??? }
          ??? ??? ??? ??? }
          ??? ??? ??? }
          ??? ??? ??? if(req)
          ??? ??? ??? {
          ??? ??? ??? ??? var url = "google_suggest.php";
          ???????
          ??? ??? ??? ??? req.onreadystatechange = processReqChange;
          ??? ??? ??? ??? req.open("POST", url, true);

          ??????? ??? ??? req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
          ??? ??? ??? ??? req.setRequestHeader("Method", "POST " + url + " HTTP/1.1");
          ??? ??? ??? ??? req.send("q=" + escape(document.QForm.qtext.value));
          ??? ??? ??? }
          ??? ??? ???

          ??? ??? }
          ??? ???
          ??? ??? function processReqChange()
          ??? ??? {
          ??? ??? ??? if(req.readyState == 4) // only if req shows "loaded"
          ??? ??? ??? {
          ??? ??? ???????????????? if (req.status == 200) // only if "OK"
          ??? ??? ???????????????? {
          ??? ??? ???????????????? ??? ??? x = req.responseText;
          ??? ??? ???????????????????????? eval(x);
          ??
          ? ??? ???????????????? }
          ??? ??? ???????????????? else
          ??? ??? ???????????????? {
          ??? ??? ?????????? ??? ??? ????? alert("There was a problem retrieving the XML data:\n" + req.statusText);
          ??? ??? ???????????????? }
          ??? ??? ??? }
          ??? ??? ??? else if(req.readyState == 2)
          ??? ??? ??? {
          ??? ??? ??? }
          ??? ??? }
          ??? ???
          ??? ??? function sendRPCDone(frameElement, qString, arr1, arr2, arr3)
          ??? ??? {
          ??? ???
          ??? ??? ??? var suggest_results = eval(arr1);
          ??? ??? ??? var counts = eval(arr2);
          ??? ??? ??? var htmlstr = "<TABLE cellspacing=4 border=0>";
          ??? ??? ??? for (var i=0; i < suggest_results.length; i++)
          ??? ??? ??? {
          ??? ??? ??? ??? htmlstr += "<tr><td><a href=\"javascript:self.location=\'http://www.google.com/search?hl=en&q=" + suggest_results[i] + "&btnG=Google+Search\'\">" + suggest_results[i] + "</a></td>";
          ??? ??? ??? ??? htmlstr += "<TD width=200><font color= 228b22>" + counts[i] + "</font></TD></TR>"
          ??? ??? ?????? ??? ?
          ??? ??? ??? }
          ??? ??? ??? htmlstr += "</TABLE>";
          ??? ??? ??? document.getElementById("google_suggest_target").innerHTML = htmlstr;
          ??? ???
          ??? ??? }
          ??? ???
          ??? ??? </script>

          4。家庭作業(yè) :)

          一定要自己寫一些代碼,才能鞏固知識(shí):)
          題目:
          我們經(jīng)常用del.icio.us來收藏我們喜歡的網(wǎng)站或者文章,并加一些類似讀書筆記的注釋。那么我們怎么利用del.icio.us提供的API來訪問我們的讀書筆記信息,并顯示在自己的Blog里呢?
          提示:
          1。你要有一個(gè)del.icio.us的賬號(hào),并且已經(jīng)有所網(wǎng)頁收藏作為實(shí)驗(yàn)數(shù)據(jù):)
          2。API URL 是 "http://del.icio.us/feeds/json/" + "你的賬號(hào)名";自己參看一下,看返回什么樣的格式文本。另外,如果要限制返回的記錄數(shù),可以加"?count=10"這樣的參數(shù)。


          最后,祝大家中秋愉快!

          ---------------------------完----------------------------




          posted on 2006-10-07 07:05 Dedian 閱讀(2247) 評(píng)論(2)  編輯  收藏 所屬分類: Java Memo
          評(píng)論:
           
          Copyright © Dedian Powered by: 博客園 模板提供:滬江博客
          主站蜘蛛池模板: 永胜县| 凤冈县| 伊金霍洛旗| 襄城县| 陈巴尔虎旗| 金湖县| 岫岩| 抚松县| 保靖县| 通城县| 定安县| 修文县| 托里县| 梓潼县| 垫江县| 灵川县| 余江县| 晋中市| 平果县| 深州市| 惠东县| 辉南县| 宜丰县| 江达县| 高尔夫| 灌阳县| 三台县| 江孜县| 米林县| 融水| 高尔夫| 额济纳旗| 永川市| 岳池县| 九龙坡区| 桂平市| 佳木斯市| 卓资县| 得荣县| 玉山县| 宿迁市|