3月10日——培訓第76天

今天講Ajax,還是那天試講的年輕人,他叫王興魁。

回顧一下上次說過的內容:

A New Approach to Web Pllication XML
Asynchronized javascript and xml

對錶單數據的校驗不需要打開新的頁面或是提交整個頁面數據
不刷新頁面動態修改頁面內容,減少用戶的等待時間。
只是從服務器端獲取需要的數據,而不是一次獲取所有的數據。

一個校驗用戶名的實例:

一個文本框,一個按鈕(檢驗用戶名是否存在)

<body>
<form action="Classic" method="POST">
 <input type="text" id="name">
 <input type="submit" value="校驗" >
</form>
</body>

public class Classic extends HttpServlet
{
 protected void doPost
 {
  response.setContentType("text/html;charset=gbk");
  response.setHeader("Cache-Control","no-cache");

  PrintWriter out = response.getWriter() ;
  String name = request.getParameter("name");
  if("wangxingkui".equals(name))
  {
   out.println("存在");
  }
  else
  {
   out.println("不存在");
  }
  out.println("<a href='Classic.html'>返回Classic.html</a>");
 }
 
};

如果是採用ajax的話,html頁面應該這麼寫:

<body>
<input type="text" id="name">
<input type="button" id="submit" οnclick="check()">

<script type="text/javascript">
 var xmlhttp;
 function check()
 {
  if(window.XMLHttpRequest)//這個if分支是用來處理非IE瀏覽器的。
  {
   xmlhttp = new XMLHttpRequest();
   if(xmlhttp.overrideMimeType)//需要覆蓋MimeType
   {
    xmlhttp.overrideMimeType("text/xml");
   }
  }
  if(window.ActiveXObject)//這個if邏輯分支是用來處理IE瀏覽器的。
  {
   var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
    'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0',
    'MSXML2.XMLHTTP.3.0'];
   for(var i=0 ; i<microsoft.length; i++)
   {
    try
    {
     //嘗試建立xmlhttp對象
     xmlhttp=new ActiveXObject(microsoft[i]);
     break ;
    }
    catch(e)
    {
    
    }
   }
  }
  if(xmlhttp)
  {
   var username = document.getElementById("name").value;
   //得到文本框中的用戶名的value!
   
   xmlhttp.onreadystatechange = callback ;
   //給xmlhttp對象設置回調方法
   
   xmlhttp.open("GET","AJAX?name=" + username,true); //爲了和服務器建立一個連接
   //其實open方法共有5個參數:第一個參數,指定和服務器之間數據交互的方式
   //第二個參數是url,第三個是設置xmlhttp是否用異步方式實現,如果是false的話,
   //就是同步方式,不會再去調用callback方法,
   
   //xmlhttp.open("POST","AJAX",true);採用post方式的open方法
   //xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
   //如果是是post方式提交的話,還必須設置xmlhttp對象的請求頭!

   xmlhttp.send(null);  //發送數據

   //xmlhttp.send("name=" + username);如果是post提交的話,在send中不能再寫null了,
   //而是要拼接好你要傳送過去的信息,然後再send過去。

  }
  else
  {
   alert("建立xmlhttprequest失敗!");
  }

 }
 
 
 function callback()
 {
  //服務器端數據都發過來的時候,readyState值爲4
  if(xmlhttp.readyState == 4)
  {
   if(xmlhttp.status == 200)
   {
    //服務器以純文本的方式返回數據,數據賦給text變量。
    var text = xmlhttp.responseText ;
    alert(text) ;
   }
  }
 }
</script>
</body>


Servlet則做少許改動即可:

public class Classic extends HttpServlet
{
 protected void doPost
 {
  response.setContentType("text/html;charset=gbk");
  response.setHeader("Cache-Control","no-cache");

  PrintWriter out = response.getWriter() ;
  String name = request.getParameter("name");
  if("wangxingkui".equals(name))
  {
   out.println("存在");
  }
  else
  {
   out.println("不存在");
  }
  
 }
 
};

AJAX應用的5個步驟:
1、建立XMLHttpRequest對象
2、設置回調函數(服務器端消息回來後用這個函數做相應處理)
3、使用open方法建立連接
4、send方法發送數據
5、在回調函數中針對不同響應狀態進行相應的處理。

還有不同瀏覽器創建XMLHttpRequest對象的方式不同
設置onreadystatechange需要注意
GET和POST方式提交時候send和open方法需要注意的區別
如何得知服務器的處理結束返回(在callback中處理)
返回的數據類型可以是純文本也可以是xml類型(responseText和responseXML)

================================================================

XMLHttpRequest的一個特殊性的安全問題:不能夠跨域訪問。
IE:訪問跨域頁面時會給出提示,用戶確認後可以訪問
FireFox或其他:不允許訪問跨域頁面。

解決方法實例:通過一種代理方式(讓服務器端代理去訪問url信息,然後返回給客戶端)

//判斷這個url地址是否是同域上的
function convertURL(url)
{
 //如果是http://開頭的話,我們認爲是跨域訪問
 if(url.substring(0,7) == "http://")
 {
  return "Proxy?url" + url ;//然後將url轉爲代理
 }
 return url ;
}

然後在服務器端
public class Proxy extends HttpServlet
{
 protected void doPost()
 {
  String url = request.getParameter("url");
  URL connect = new URL(url) ;
  BufferedReader reader =
   new BufferedReader(new InputStreamReader(connect.openStream()));
  String line ;
  PrintWriter out = response.getWriter() ;
  while((line = reader.readLine())!=null)
  {
   out.println(line) ;
  }

 }
}

================================================================================

使用GET和POST兩種方式完成一個校驗電子郵件地址的小程序
符合條件的電子郵件應滿足一下規則
包含@
以.com .net .cn .org .edu結尾

以xml的格式send數據

服務器端解析的主要方式:
BufferedReader r = request.getReader();

上述問題的答案:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title></title>
</head>
<body>
    <input type="text" id="email"/>
    <input type="button" value="校驗" οnclick="check()"/>

    <script type="text/javascript">
        function check(){
            var myxmlhttp = new MyXMLHttpRequest();
            var email = document.getElementById("email").value;
            myxmlhttp.send("POST","AJAX","<email>" + email + "</email>",mycallback);
        }
        function mycallback(responsetext){
            alert(responsetext);   
        }


        var MyXMLHttpRequest = function(){
            if(window.XMLHttpRequest){
                this.xmlhttp = new XMLHttpRequest();
                if(this.xmlhttp.overrideMimeType){
                    this.xmlhttp.overrideMimeType("tex/xml");
                }
            } else if(window.ActiveXObject){
                var microsoft = ['Micosoft.XMLHTTP','MSXML2.XMLHTTP'
                        ,'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0'
                        ,'MSXML2.XMLHTTP.3.0'];
                for(var i=0; i<microsoft.length; i++){
                    try{
                        this.xmlhttp = new ActiveXObject(microsoft[i]);
                        break;
                    } catch(e){

                    }
                }
            } else{
                this.xmlhttp = null;
            }
        }
        MyXMLHttpRequest.prototype.send = function(method,url,data,usercallback){
            var xmlhttp = this.xmlhttp;
            this.xmlhttp.onreadystatechange = function(){
                if(xmlhttp.readyState == 4){
                    if(xmlhttp.status == 200){
                         usercallback(xmlhttp.responseText);
                    }
                }
            };
            this.xmlhttp.open(method,url,true);
            if(method == "POST"){
                this.xmlhttp
     .setRequestHeader("Content-Type","application/x-www-form-urlencoded");
            }
            this.xmlhttp.send(data);
        }
    </script>

</body>
</html>

/**
 * Created by IntelliJ IDEA.
 * User: Administrator
 * Date: 2007-3-10
 * Time: 10:46:30
 * To change this template use File | Settings | File Templates.
 */

import java.io.PrintWriter;
import java.io.BufferedReader;

public class AJAX extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request,
  javax.servlet.http.HttpServletResponse response)
  throws javax.servlet.ServletException, java.io.IOException
 {
        response.setContentType("text/html;charset=GB2312");
        response.setHeader("Cache-Control","no-cache");
        BufferedReader reader = request.getReader();
       
        PrintWriter out = response.getWriter();
        String line = reader.readLine();
        String email = line.substring(6,line.indexOf("</"));
        //String email = request.getParameter("email");
        if(email != null){
            if(email.indexOf("@") > 0 &&
                    (email.endsWith(".com") || email.endsWith(".net")
                    || email.endsWith(".cn") || email.endsWith(".edu")
                    || email.endsWith(".org"))){
                out.println("email符合要求");
            } else{
                out.println("email不符合要求");
            }
        } else{
                out.println("email不符合要求");   
        }
    }

    protected void doGet(javax.servlet.http.HttpServletRequest request,
  javax.servlet.http.HttpServletResponse response)
  throws javax.servlet.ServletException, java.io.IOException {
        doPost(request,response);
    }
}

=============================================================================

DOM(文檔對象模型)是表示和處理HTML或XML文檔各元素的應用程序接口(API)。
HTML的DOM和XML的DOM在API接口上基本一致,使用差別不大,但本質上有區別。
HTML的DOM是一個內存對象樹,在瀏覽器中只保存一份,HTML的DOM修改HTML的內容會直接反應
到瀏覽器中;而XML的DOM則可以創建多個,每個可以對應一個XML文件。

<html>

<head><title>yuan</title></head>
<body οnlοad="show()">
 <input type="text" />
 <div>Hello</div>
 <script type="text/javascript">
  function show()
  {
   //返回html的根節點這一層的所有子節點
   //var htmlnodes = document.childNodes[1];
   var nodes = document.body.childNodes ; //遍歷body標籤體中的所有節點。
   for(var i=0 ; i< nodes.length ; i ++)
   {
    var node = nodes[i];
    alert("NodeName:"+node.nodeName+"NodeValue:"+node.nodeType);
   }
  }
 </script>
</body>

</html>
==================================================
如果不想讓提示信息用提示框的形式出現,而是直接出現在頁面裏面的話,可以在頁面中設置一個
div層,然後在相應的callback方法 中寫四行代碼如下:
<div id="message"></div>


var text = xmlhttp.responseText ;
var div = document.getElementById("message")
var textnode=document.createTextNode(text);
div.appendChild(textnode);


還可以這麼來:
var text = xmlhttp.responseText ;
var div = document.getElementById("message")
div.innerHTML = text ;
//這也是可以的!

======================================================
聯動菜單:

服務器端的Servlet:

String year = request.getParameter("year");
String city = request.getParameter("city");
String number = (String)yearCityNumberMap.get(year+"&"+city);

//init方法中將hashMap中設置好數值
yearCityNumberMap.put("2007&beijing","150");
……………………………………………………………………………………………………

客戶端的html:
<select id="year" οnchange="updateList()">
 <option value="">Select One</option>
 <option value="2006">2006</option>
 <option value="2007">2007</option>
</select>

<select id="city" οnchange="updateList()">
 <option value="">Select One</option>
 <option value="beijing">beijing</option>
 <option value="shanghai">shanghai</option>
</select>

<select id="number"></select> //這個下拉框的內容是根據前兩個動態生成的。

腳本中的關鍵代碼:

<script type="text/javascript">
 function show()
 {
  document.getElementById("year").value
 }
 
 function callback(responseText)
 {
  clear();
  var optionnode = document.createElement("option");
  var text = document.createTextNode(responseText);
  optionnode.appendChild(text);
  var selectnode = document.getElementById("number");
  selectnode.appendChild(optionnode);
 }
 
 function clear()
 {
  var selectnode = document.getElementById("number");
  var nodes = document.getElementById("number").childNodes ;
  while(nodes.length)
  {
   //每次移除掉一個select子節點
   selectnode.recoveChild(nodes[0]);
  }
 }

</script>
==============================
聯動菜單的真實源代碼:

服務器端:

/**
 * Created by IntelliJ IDEA.
 * User: xingxing
 * Date: 2007-3-9
 * Time: 23:10:03
 * To change this template use File | Settings | File Templates.
 */

import java.io.PrintWriter;
import java.util.HashMap;

public class List extends javax.servlet.http.HttpServlet {
    HashMap yearCityNumberMap = new HashMap();

    protected void doPost(javax.servlet.http.HttpServletRequest request,
   javax.servlet.http.HttpServletResponse response)
  throws javax.servlet.ServletException, java.io.IOException
 {

        response.setContentType("text/html;charset=GB2312");
        response.setHeader("Cache-Contorl","no-cache");

        PrintWriter out = response.getWriter();

        String year = request.getParameter("year");
        String city = request.getParameter("city");
        System.out.println(year+"&"+city);
        String number =  (String) yearCityNumberMap.get(year+"&"+city);


        out.println(number);
    }

    protected void doGet(javax.servlet.http.HttpServletRequest request,
  javax.servlet.http.HttpServletResponse response)
  throws javax.servlet.ServletException, java.io.IOException
 {
        doPost(request,response);
    }
    public void init(javax.servlet.ServletConfig servletConfig)
  throws javax.servlet.ServletException
 {
        System.out.println("init");
        yearCityNumberMap.put("2007&beijing","150");
        yearCityNumberMap.put("2006&beijing","145");
        yearCityNumberMap.put("2007&shanghai","140");
        yearCityNumberMap.put("2006&shanghai","135");

        //初始化數據

        //數據庫應用
    }
}


客戶端:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title></title>
</head>
<body>
    年份

    <select id="year" οnchange="updateList()">
        <option value="">Select One</option>
        <option value="2007">2007</option>
        <option value="2006">2006</option>
    </select>
    城市
    <select id="city" οnchange="updateList()">
        <option value="">Select One</option>
        <option value="beijing">beijing</option>
        <option value="shanghai">shanghai</option>
    </select>
    人口

    <select id="number"></select>
    萬
    <script type="text/javascript">
         var xmlhttp;
        function updateList(){
             if(window.XMLHttpRequest){
                xmlhttp = new XMLHttpRequest();
                if(window.overrideMimeType){
                    xmlhttp.overrideMimeType('text/xml');
                }
            } else{
                var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
                        'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0'];
                for(var i=0; i<microsoft.length; i++){
                    try{
                        xmlhttp = new ActiveXObject(microsoft[i]);
                        break;
                    }catch(e){

                    }
                }
            }
            if(xmlhttp == null ){
                alert("建立XMLHttpRequest對象失敗");
            } else{
                xmlhttp.open("POST","List",true);
                xmlhttp.onreadystatechange = callback;
                xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
                var year = document.getElementById("year").value;
                var city = document.getElementById("city").value;
                if(year != "" && city != ""){
                    xmlhttp.send("year=" + year + "&city=" + city);
                } else{
                    clear();
                }
            }
        }
        function callback(){
            if(xmlhttp.readyState == 4){
                if(xmlhttp.status == 200){
                    var number = xmlhttp.responseText;
                    clear();
                    var optionNode = document.createElement("option");
                    optionNode.appendChild(document.createTextNode(number));
                    document.getElementById("number").appendChild(optionNode);

                }
            }
        }

        function clear(){
            var number = document.getElementById("number");
            while(number.childNodes.length > 0) {
                number.removeChild(number.childNodes[0]);
            }
        }
    </script>
</body>
</html>

====================================================================
如果返回的響應內容不是文本形式而是XML形式的話,需要客戶端裏面使用DOM來解析。
比如:
function mycallback(responseXML)
{
 var docum = responseXML ;
 var message = docum.getElementsByTagName("message");
 var text = message[0].firstChildnodeValue;
}

DOM與XML
 在處理XML文檔中兩個節點之間的空格時,IE和以Firefox爲代表的其他瀏覽器在實現上並不相同。
 其中IE會忽略掉兩個節點中的空格內容,而FireFox則會將這些空格也當作是一個一個的節點。

//針對FireFox類的瀏覽器去除XML文檔中兩個節點間的空格
function removeWhitespace(xml)
{
  var loopIndex;
  for (loopIndex = 0; loopIndex < xml.childNodes.length;loopIndex++) {
    var currentNode = xml.childNodes[loopIndex];
    //當節點是Element類型時,則遞歸調用這個方法,移除該節點的子節點間的空格
   if (currentNode.nodeType == 1) {
     removeWhitespace(currentNode);
   }
   //當節點是Text類型且節點內容是一個或多個空格時,則將此節點移除。
   if (((/^/s+$/.test(currentNode.nodeValue))) &&(currentNode.nodeType == 3)) {
     xml.removeChild(xml.childNodes[loopIndex--]);
   }
 }
}

----------------------------------------------------------
舉個例子說明一下:

<books>
 <book>
  <user>wang</user>
 </book>
</books>

如果是IE處理的話books的childnodes就只有book,book的childnodes就只有user
如果是火狐的話,根節點是book,下面有很多的節點(其中包括book和許多空格和回車組成的節點)

所以如果是火狐瀏覽器處理的話,必須得考慮這個空格和回車符的處理問題,必須將它們忽略掉。

===========================================================================

DOM與XML

 使用過DOM4j的人可能都知道可以利用其中的XPATH方式直接獲取任意深度的一個節點。

 在IE6.0及其以後版本中我們可以使用同樣的方式來訪問任意深度的XML數據,這給XML數據的
 解析操作帶來了便利。

 但是在FireFox等瀏覽器中,則是使用了DOM標準的XPATH處理方式,沒有IE這麼簡單的方式。

 //獲得第一個book節點中的第一個author節點
 var anode = xmlDoc.selectSingleNode("book/author")
 //獲得第一個book節點中的第一個author節點的文本內容
 var author = xmlDoc.selectSingleNode("book/author/text()").nodeValue

 //獲得第一個book節點中的第一個包含age屬性的author節點
 var author = xmlDoc.selectSingleNode("book/author[@age]")
 //獲得所有book節點下的author節點
 var author = xmlDoc.selectNodes(“book/author")

===============================================================
封裝XPATH方法,解決IE與其他瀏覽器之間的不同

/**
* 封裝selectSingleNode方法,返回滿足XPATH表達式的第一個節點
* @paran xmldoc 表示要查找的XML文檔
* @param sXPath XPATH表達式
*/
function selectSingleNode(xmldoc,sXPath){
//如果瀏覽器是IE
if(window.ActiveXObject){
//使用IE的XPATH方式獲得節點
return xmldoc.selectSingleNode(sXPath);
} else{
//FireFox類瀏覽器的處理方式
var oEvaluator = new XPathEvaluator();
    if(oEvaluator != null){
      var oResult = oEvaluator.evaluate(sXPath,xmldoc,null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
      return oResult.singleNodeValue;
    } else{
      return null;
    }
}
}

/**
* 封裝selectNodes方法,以數組方式返回滿足XPATH表達式的所有節點
* @paran xmldoc 表示要查找的XML文檔
* @param sXPath XPATH表達式
*/
function selectNodes(xmldoc,sXPath){
//如果瀏覽器是IE
  if(window.ActiveXObject){
    //使用IE的XPATH方式獲得節點
    return xmldoc.selectNodes(sXPath);
} else{
    //FireFox類瀏覽器的處理方式
    var oEvaluator = new XPathEvaluator();
    if(oEvaluator != null){
       var oResult = oEvaluator.evaluate(sXPath,xmldoc,null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
       var nodes = new Array;
       var node;
       while(node=oResult.iterateNext()){
         nodes.push(node);
       }
       return nodes;
} else{
return null;
}
}
}

===============================================================
IE與其他瀏覽器還可以新建xml文檔對象或裝載xml文檔對象。
封裝方法如下:
/**
* 封裝裝載XML的方法,並返回XML文檔的根節點。
* @param flag true時參數xml表示xml文檔的名稱;false時參數xml是一個字符串,其內容是一個xml文檔
* @param xml 根據flag參數的不同表示xml文檔的名稱或一個xml文檔的字符串表示
* @param fload 表示xml文檔裝載完成時調用的方法,可以爲null
*/
function loadXML(flag,xml,fload){
var xmlDoc;
//針對IE瀏覽器
if(window.ActiveXObject){
var aVersions = ["Microsoft.XmlDom",
"MSXML2.DOMDocument.5.0","MSXML2.DOMDocument.4.0",
"MSXML2.DOMDocument.3.0","MSXML2.DOMDocument"];
for (var i = 0; i < aVersions.length; i++) {
try {
//建立xml對象
var xmlDoc = new ActiveXObject(aVersions[i]);
break;
} catch (oError) {
}
}
if(xmlDoc != null){
xmlDoc.onreadystatechange = function(){
//文檔裝載完成時
if(xmlDoc.readyState == 4){
//文檔裝載完成後做相關處理
if(fload != null){
            fload(xmlDoc);
          }
}
}
//根據XML文檔名稱裝載
if(flag == true){
        xmlDoc.load(xml);
} else{
        //根據表示XML文檔的字符串裝載
        xmlDoc.loadXML(xml);
}
//返回XML文檔的根節點。
return xmlDoc.documentElement;
}
} else{
//針對非IE瀏覽器
    if(document.implementation && document.implementation.createDocument){
      /*
       第一個參數表示XML文檔使用的namespace的URL地址
       第二個參數表示要被建立的XML文檔的根節點名稱
       第三個參數表示要建立的文檔類型
       這裏我們要裝載一個已有的XML文檔,所以首先建立一個空文檔,因此使用下面的方式
      */
      xmlDoc = document.implementation.createDocument("","",null);
      if(xmlDoc != null){
        xmlDoc.onload = function(){
          //文檔裝載完成後做相關處理
          if(fload != null){
            fload(xmlDoc);
          }
        }
        //根據XML文檔名稱裝載
        if(flag == true){
          xmlDoc.load(xml);
        } else{
          //根據表示XML文檔的字符串裝載
          var oParser = new DOMParser();
          xmlDoc = oParser.parseFromString(xml,"text/xml");
        }
        //返回XML文檔的根節點。
        return xmlDoc.documentElement;
      }
    }
}
  return null;
}


===================================================================

firefox中處理XPath是如何去做的:

//xmldoc是通過XMLHttpRequest獲取的響應XML數據,內容如上面所示
var xmldoc = xhr.responseXML
//FireFox中需要使用XPathEvaluator對象來獲取指定path的XML數據
var oEvaluator = new XPathEvaluator();
//定義XPATH的表達式,這裏還是獲取book節點下的author節點
var sXPath = "book/author";
/*
 evaluate方法用於獲取指定path的XML,共有五個輸入參數:
 (1)XPATH的表達式
 (2)XML文檔對象
 (3)用於解析那namespace的方法
 (4)evaluate方法返回類型,共十種,這裏給出常用的幾種,其餘可參考《JavaScript權威指南》
  (JavaScript The Definitive Guide)
1) XPathResult.ORDERED_NODE_ITERATOR_TYPE返回的XPathResult對象中包含的是Node節點集合,
 節點順序和文檔中的順序相同。可以在while循環中通過XPathResult對象的iterateNext方法依次
 獲得所有節點。此種方式不允許在遞歸獲取所有節點的過程中修改文檔內容。

2) XPathResult.ORDERED_NODE_SNAPSHOT_TYPE返回的XPathResult對象中包含的是Node節點集合,
 節點順序和文檔中的順序相同。此時XPathResult對象中的snapshotLength屬性表示返回的節點個數,
 可以在for循環中通過XPathResult對象的snapshotItem(index)方法依次獲得所有節點。此種方式由
 於得到的是一個snapshot(鏡像),因此文檔內容的變化不會影響到循環獲取節點。

3) XPathResult.FIRST_ORDERED_NODE_TYPE 類似於IE中的selectSingleNode方法的效果,返回符合
 XPATH路徑的第一個節點,可通過XPathResult對象的singleNodeValue屬性獲得這個節點。

4) XPathResult.STRING_TYPE返回符合XPATH路徑的第一個節點,並在XPathResult對象的stringValue
 屬性中保存這個節點的文本信息,對於上面的示例XML,則會返回”wang”。

5) 存儲根據指定path獲取到的XML節點,應爲XPathResult類型對象,如果null,則通過evaluate返回一個
 新的XPathResult類型對象。
*/
//這裏使用XPathResult.ORDERED_NODE_ITERATOR_TYPE的方式獲得相應節點
var oResult = oEvaluator.evaluate(sXPath, xmldoc,null,
XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);

if (oResult != null) {
var oElement;
//使用while循環,通過iterateNext方法獲得所有匹配的節點
while (oElement = oResult.iterateNext()) {
    //顯示當前節點的文本內容
        alert(oElement.firstChild.nodeValue); 
}
}


==========================================================================================


一個ajax實現的簡單學生管理系統:

服務器端:

import java.io.*;
import java.util.Random;

import javax.servlet.*;
import javax.servlet.http.*;

public class StudentListServlet extends HttpServlet {
   
    protected void addStudent(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
       
        //Store the object in the database
        String uniqueID = storeStudent();
       
        //Create the response XML
        StringBuffer xml = new StringBuffer("<result><uniqueID>");
        xml.append(uniqueID);
        xml.append("</uniqueID>");
        xml.append("<status>1</status>");
        xml.append("</result>");
        //數據庫操作

        //Send the response back to the browser
        sendResponse(response, xml.toString());
    }
   
    protected void deleteStudent(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
       
        String id = request.getParameter("id");
        /* Assume that a call is made to delete the employee from the database */
       
        //Create the response XML
        StringBuffer xml = new StringBuffer("<result>");
        xml.append("<status>1</status>");
        xml.append("</result>");
        //數據庫操作

        //Send the response back to the browser
        sendResponse(response, xml.toString());
    }
   
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        String action = request.getParameter("action");
        if(action.equals("add")) {
            addStudent(request, response);
        }
        else if(action.equals("delete")) {
            deleteStudent(request, response);
        }
    }
   
    private String storeStudent() {
        /* Assume that the employee is saved to a database and the
         * database creates a unique ID. Return the unique ID to the
         * calling method. In this case, make up a unique ID.
         */
        String uniqueID = "";
        Random randomizer = new Random(System.currentTimeMillis());
        for(int i = 0; i < 8; i++) {
            uniqueID += randomizer.nextInt(9);
        }
       
        return uniqueID;
    }
   
    private void sendResponse(HttpServletResponse response, String responseText)
    throws IOException {
        response.setContentType("text/xml");
        response.getWriter().write(responseText);
    }
}


客戶端:

基本工作流程:add按鈕點擊後,創建xm1httpRequest,然後從輸入框裏面將信息取出來,用xmlhttpRequest
將信息發給服務器,然後服務器操作數據庫,返回響應;如果成功的話,動態生成列表,列表中的每一行信息還要
附加好一個刪除按鈕,每個刪除按鈕還要附帶一個onclick事件!這些都是要用dom創建節點的方式來做。
如果失敗的話,就好辦了,只需要返回個錯誤信息到客戶端就可以了。

如果刪除一個用戶的話,前面創建列表的時候每個刪除按鈕都對應着delete方法,方法裏面還是先創建
xmlhttprequest,然後發送信息(只需要傳送id給服務器端就可以了),服務器根據id信息去刪除,要麼
成功,要麼失敗;成功的話,用html的dom將child節點remove掉(不需要像上面設置button那些麻煩事情了),
失敗的話,比成功的時候簡單多了,還是一樣,返回個信息給客戶端就ok了

代碼:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Employee List</title>

<script type="text/javascript">
var xmlHttp;
var name;
var number;
var classname;
var action;
var deleteID;
var EMP_PREFIX = "emp-";

function createXMLHttpRequest() {
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();
        if(window.overrideMimeType){
            xmlHttp.overrideMimeType('text/xml');
        }
    } else{
        var microsoft = ['Microsoft.XMLHTTP','MSXML2.XMLHTTP',
            'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0','MSXML2.XMLHTTP.3.0'];
        for(var i=0; i<microsoft.length; i++){
            try{
                xmlHttp = new ActiveXObject(microsoft[i]);
                break;
            }catch(e){
            }
        }
    }
}
   
function addStudent() {
    name = document.getElementById("name").value;
    number = document.getElementById("number").value;
    classname = document.getElementById("classname").value;
    action = "add";

    if(name == "" || number == "" || classname == "") {
        return;
    }
   
    var url = "StudentListServlet?"
        + createAddQueryString(name, number, classname, "add")
        + "&ts=" + new Date().getTime();
       
    createXMLHttpRequest();
    xmlHttp.onreadystatechange = handleAddStateChange;
    xmlHttp.open("GET", url, true);
    xmlHttp.send(null);
}

function createAddQueryString(name, title, department, action) {
    var queryString = "name=" + name
        + "&number=" + number
        + "&classname=" + classname
        + "&action=" + action;
    return queryString;
}

   //接收響應的時候
function handleAddStateChange() {
    if(xmlHttp.readyState == 4) {
        if(xmlHttp.status == 200) {
            updateStudentList();//添加數據
            clearInputBoxes();//清除輸入框!
        }
        else {
            alert("Error while adding employee.");
        }
    }
}

function clearInputBoxes() {
    document.getElementById("name").value = "";
    document.getElementById("number").value = "";
    document.getElementById("classname").value = "";
}

function deleteStudent(id) {
    deleteID = id;
   
    var url = "StudentListServlet?"
        + "action=delete"
        + "&id=" + id
        + "&ts=" + new Date().getTime();
       
    createXMLHttpRequest();
    xmlHttp.onreadystatechange = handleDeleteStateChange;
    xmlHttp.open("GET", url, true);
    xmlHttp.send(null);
}

function updateStudentList() {
    var responseXML = xmlHttp.responseXML;
 
 //看status是否滿足條件
    var status = responseXML.getElementsByTagName("status").item(0).firstChild.nodeValue;
    status = parseInt(status);
    if(status != 1) {
        return;
    }

    //下面開始建表了
    var row = document.createElement("tr");
    var uniqueID = responseXML.getElementsByTagName("uniqueID")[0].firstChild.nodeValue;
    row.setAttribute("id", EMP_PREFIX + uniqueID);
   
 //每次都新建一個td,然後將內容放進去。
    row.appendChild(createCellWithText(name));
    row.appendChild(createCellWithText(number));
    row.appendChild(createCellWithText(classname));
   
 //這部分是創建button!
    var deleteButton = document.createElement("input");
    deleteButton.setAttribute("type", "button");
    deleteButton.setAttribute("value", "刪除");
    deleteButton.onclick = function () { deleteStudent(uniqueID); };
 //這個onclick屬性在IE中無法通過setAttribute的方式設置屬性!!!
    var cell = document.createElement("td");
    cell.appendChild(deleteButton);
    row.appendChild(cell);
   
    document.getElementById("studentList").appendChild(row);
    updateEmployeeListVisibility();
}

function createCellWithText(text) {
    var cell = document.createElement("td");
    cell.appendChild(document.createTextNode(text));
    return cell;
}

function handleDeleteStateChange() {
    if(xmlHttp.readyState == 4) {
        if(xmlHttp.status == 200) {
            deleteEmployeeFromList();
        }
        else {
            alert("Error while deleting employee.");
        }
    }

}

function deleteEmployeeFromList() {
    var status = xmlHttp.responseXML.getElementsByTagName("status")
  .item(0).firstChild.nodeValue;
    status = parseInt(status);
    if(status != 1) {
        return;
    }//判斷服務器端是否真的已經將數據處理完了。
   
 //根據ID找到節點,然後刪除!
    var rowToDelete = document.getElementById(EMP_PREFIX + deleteID);
    var employeeList = document.getElementById("studentList");
    employeeList.removeChild(rowToDelete);
   
    updateEmployeeListVisibility();
}

function updateEmployeeListVisibility() {
    var employeeList = document.getElementById("studentList");
    if(employeeList.childNodes.length > 0) {
        document.getElementById("studentListSpan").style.display = "";
    }
    else {
        document.getElementById("studentListSpan").style.display = "none";
    }
}
</script>
</head>

<body>
  <h1>學生管理系統</h1>
 
    <table width="80%" border="0">
        <tr>
            <td>姓名: <input type="text" id="name"/></td>
            <td>學號: <input type="text" id="number"/></td>
            <td>班級: <input type="text" id="classname"/></td>
        </tr>
    </table>
    <input type="button" value="增加" οnclick="addStudent()"/>

  <span id="studentListSpan" style="display:none;">
  <h2>學生:</h2>
 
  <table border="1" width="80%">
    <tbody id="studentList"></tbody>
  </table>
  </span>
</body>
</html>
================================================================

ajax還可以實現那種服務器和客戶端自動定時交互的功能。比如隔多長時間自動從服務器端
獲取某可能頻繁改變的數據,然後通過不刷新頁面的方式來實現改變客戶端數據的效果。

下面的代碼涉及了ajax中的樣式設置的細節,比如setTimeout方法就是一個典型例子
timeoutid = setTimeout(show,1000); 每隔1000ms運行一次show方法,返回的
           timeoutid傳給clearTimeout就可以停止
           這種定時的功能!

代碼如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title></title>
</head>
<body οnlοad="show()">
    當前股票指數:<span id="level"></span>
    <input type="button" value="stop refresh" id="stop" οnclick="stop()"/>
    <script type="text/javascript">
        var timeoutid;
        function show(){
            var myxmlhttp = new MyXMLHttpRequest();
            myxmlhttp.send("POST","Refresh","",mycallback);
            timeoutid =  setTimeout(show,1000);
        }
        function mycallback(responsetext){
            var divnode = document.getElementById("level");
            if(responsetext - 0 > 2500){
                divnode.style.backgroundColor = "red";
            }else{
                divnode.style.backgroundColor = "yellow";
            }
            divnode.innerHTML = responsetext;
        }
        var MyXMLHttpRequest = function(){
            if(window.XMLHttpRequest){
                this.xmlhttp = new XMLHttpRequest();
                if(this.xmlhttp.overrideMimeType){
                    this.xmlhttp.overrideMimeType("tex/xml");
                }
            } else if(window.ActiveXObject){
                var microsoft = ['Micosoft.XMLHTTP','MSXML2.XMLHTTP'
                        ,'MSXML2.XMLHTTP.5.0','MSXML2.XMLHTTP.4.0'
                        ,'MSXML2.XMLHTTP.3.0'];
                for(var i=0; i<microsoft.length; i++){
                    try{
                        this.xmlhttp = new ActiveXObject(microsoft[i]);
                        break;
                    } catch(e){

                    }
                }
            } else{
                this.xmlhttp = null;
            }
        }
        MyXMLHttpRequest.prototype.send =
   function(method,url,data,usercallback)
   {
            var xmlhttp = this.xmlhttp;
            this.xmlhttp.onreadystatechange = function(){
                if(xmlhttp.readyState == 4){
                    if(xmlhttp.status == 200){
                         usercallback(xmlhttp.responseText);
                    }
                }
            };
            this.xmlhttp.open(method,url,true);
            if(method == "POST"){
                this.xmlhttp.setRequestHeader("Content-Type",
     "application/x-www-form-urlencoded");
            }
            this.xmlhttp.send(data);
        }

        function stop(){
            clearTimeout(timeoutid);
        }
    </script>
</body>
</html>


=============================================================

由於自己DOM和javascript等並不是很明白,所以今天挺糊塗的,不過王興魁這小夥子,
真的挺猛的,培訓的老師就該像這個樣子纔對。老師不僅僅是要技術或是項目非常非常的
牛,最重要的一點是如果想兼職當培訓講師的話,語言表達能力是非常非常重要的,若是光
依仗着技術和經驗,但是嘴皮子不靈光的話,這樣的兼職講師,不可能會受學生的歡迎,IT
培訓是高花費,學生對培訓機構要求高、對老師語言表達能力要求高是正常的不能再正常的事
情,這沒什麼不對的。一個拙嘴笨腮的培訓講師,但非有點良心,也會覺着幹培訓這錢拿着問
心有愧吧,當然這是從理論上講,現在這社會,恐怕有這良心的人不多。

 

發佈了111 篇原創文章 · 獲贊 6 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章