Ajax實現查詢助手(Query Helper)

1       概述

1.1    查詢助手功能介紹

在通常的BS軟件項目中,查詢助手使用頻率非常高,其功能是點擊圖標,頁面上元素的值爲條件,到後臺查詢結果,彈出查詢結果對話框,選擇紀錄,關閉對話框,並且把你選擇的有關內容顯示到父頁面中指定的元素中。由於其友好的界面設計和操作性能,對用戶和設計開發人員都有很大的吸引力,但存在開發效率低,複用性差,複雜度較高等問題。

1.2    Ajax現狀和項目實踐
隨着Ajax的風靡全球,Google的推波助瀾,優秀的界面風格,局部刷新的全新感受,給人耳目一新的印象。但由於Ajax諸多javascript腳本和後臺應用的複雜性,使ajax的推廣困難重重,國內的應用大多都是玩具級,距項目實用還有不小的差距,包括Microsoft,IBM,SUN都在積極攻關研發,以提高項目開發的實用性,降低開發難度。爲了使用ajax在項目的實用性,針對查詢助手功能的Ajax做了一些有益的嘗試,特別願意和大家分享。

1.3    Ajax簡介
網上關於Ajax的文章汗牛充棟,具體的Ajax理論可以到網上搜索,這兒只做簡單介紹:

Ajax是Asynchronous JavaScript and XML的縮寫。Ajax並不是一門新的語言或技術,它實際上是幾項技術按一定的方式組合在一在同共的協作中發揮各自的作用,它包括:

Ø         使用XHTML和CSS標準化呈現

Ø         使用DOM實現動態顯示和交互

Ø         使用XML和XSLT進行數據交換與處理

Ø         使用XMLHttpRequest進行異步數據讀取;

Ø         使用JavaScript綁定和處理所有數據

Ajax的工作原理相當於在用戶和服務器之間加了—箇中間層,使用戶操作與服務器響應異步化。並不是所有的用戶請求都提交給服務器,像—些數據驗證和數據處理等都交給Ajax引擎自己來做,只有確定需要從服務器讀取新數據時再由Ajax引擎代爲向服務器提交請求。


2       Ajax查詢助手功能設計理念

查詢助手功能設計的AJAX的設計主要集中在從前臺的jsp頁面提出Ajax請求,所有的Ajax請求都提交給查詢助手中間層,查詢助手中間層自動創建查詢助手具體實現類來實現查詢助手的具體查詢功能,查詢助手具體實現類實現數據庫查詢並組織傳回前臺數據文本。傳到前臺後自動選擇不同的JavaScript函數來解析數據,並顯示到頁面的Div或者直接顯示到頁面元素中。

2.1    Ajax實現查詢助手功能示意圖如下:



3       Ajax實現詳述

3.1    Jsp前臺
在Jsp中,點擊查詢助手圖標,或者在輸入框中打回車鍵,則顯示如圖3-1界面,Ajax從後臺獲取數據顯示在前臺頁面上方,但此時頁面並未刷新,並且缺省單選按鈕選中第一行,第一行背景色爲綠色。有兩種操作可以選擇:

1)  選擇是使用上下方向鍵來選擇紀錄,上下鍵移動時紀錄背景色自動改變,單選按鈕也自動選擇。當決定選擇某一行紀錄時,點擊回車鍵。

2)  選擇使用鼠標,當鼠標移動時,紀錄的背景色發生改變。

3)  當點擊回車鍵,或者點擊鼠標左鍵時則相關內容填充到具體的頁面元素中,並把輸入焦點自動下移到指定的輸入框,並關閉選擇界面。

4)  如果你不想選擇,也可以直接點擊選擇界面右上角的關閉圖標


resized image
圖3-1

如果查詢結果爲沒有紀錄,則:

resized image
圖3-2

具體代碼如下:

3.1.1   引入js,css文件
<link rel="stylesheet" href="<%=request.getContextPath()%>/tplife/css/maginfier.css" type="text/css">

<script type="text/javascript" src="<%=request.getContextPath()%>/js/ajax/maginfier.js"></script>


組織機構查詢助手:
<br/><img src = "<%=request.getContextPath()%>/images/magifiericon.gif" 
οnclick="orgMaginfier('<%=request.getContextPath()%>','selOrg','DivShim','orgId,orgCode,orgName','0,2,1','message','','');">

<input type="text" id = "orgCode" style="width:300px"
οnkeydοwn="if(event.keyCode == 13){orgMaginfier('<%=request.getContextPath()%>','selOrg','DivShim','orgId,orgCode,orgName','0,2,1','message');
gnIsSelectCtrl = 1;}else{}">
<input type="text" id = "orgName" style="width:300px">
<input type="hidden" id = "orgId">

    
<br/>        
<div id="selOrg"  style="display:none; z-index:100" class="termFrame" ></div>    
<iframe

        id="DivShim"

        src="javascript:false;"

        scrolling="no"

        frameborder="0"

        style="position:absolute; top:0px; left:0px; display:none;">

       </iframe>  



3.1.1.1       Js文件內容:

var xmlHttp;
var maginfierName ;
var displayName ;//顯示結果Div
var displayIFrame;//顯示結果IFrame
var posNames ;//回填頁面元素數組,如currencyId,currencyAbbrName,currencyName
var valueIndexs;//回填所需值的列號,如0,1,2
var nextPos;   //回填後focus的元素名
var serverPath;
var maginfierFunction;
var tableHead = new Array();


function createXMLHttpRequest() {
  
    if (window.ActiveXObject) {
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    }
    else if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest();
    }
    
}
function keyDowm(obj, pos, value, maginfierName0, maginfierDisplayName, maginfierDisplayIFrame)
{
  if(event.keyCode == 13)//回車鍵
  {
     filled(pos, value, maginfierDisplayName, maginfierDisplayIFrame);
  }
  else if(event.keyCode == 40)//上移鍵
  {    
    document.getElementById(maginfierName0+"divrow" + obj).bgColor='';  
    
    var t = eval(obj) + 1;
    if(document.getElementById(maginfierName0+"divrow" + t) != null)
    {
        document.getElementById(maginfierName0+"divrow" + t).bgColor='#CCFF99';
    }    
    
  }
  else if(event.keyCode == 38)//下移鍵
  {
    document.getElementById(maginfierName0+"divrow" + obj).bgColor='';  
    var t = eval(obj) - 1;
    if(t >= 0)
    {
       document.getElementById(maginfierName0+"divrow" + t).bgColor='#CCFF99';
    }
  }

}
function closeDiv(maginfierDisplayName, maginfierDisplayIFrame)
{
    _termFrame=getElement(maginfierDisplayName);
    _termFrame.style.display = 'none'    
   getElement(maginfierDisplayIFrame).style.display = 'none';
}
function operationRequest(queryString, postBlock) {  
    
    var url = serverPath + "/AjaxMaginfier?" +  queryString;
    
    createXMLHttpRequest();
    xmlHttp.onreadystatechange = handleStateChange;
    xmlHttp.open("POST", url, true);    
  //    postBlock = "獲得界面元素";
  //設置大塊數據傳輸postBlock,這樣可以解決大數據量傳向後臺。
    xmlHttp.send(postBlock);
}
// 獲得界面元素
function getElement(idString)
{
return(document.all?document.all[idString]:document.getElementById(idString));
}
// 鼠標移動
function rollover(tdObject)
{
tdObject.bgColor='#CCFF99';
}
function rollout(tdObject)
{
tdObject.bgColor='';
}

function filled(keyStr, valueStr, maginfierDisplayName, maginfierDisplayIFrame)
{  
   keys = keyStr.split(",");
   values = valueStr.split("<c>");
  
   for(i = 0; i < keys.length; i++)
   {
      
      _test = getElement(keys[i]);
      _test.value = values[i];
   }      
   _termFrame=getElement(maginfierDisplayName);
   _termFrame.style.display = 'none'    
   getElement(maginfierDisplayIFrame).style.display = 'none';
   if(document.getElementById(nextPos) != null)
   {    
      document.getElementById(nextPos).focus();
   }
}

function responseDisplay() {      
    var responseText = xmlHttp.responseText;
    var responseContent = responseText.split("|");
    var dataText = responseContent[0];
   if(dataText.length == 0)
   {
       var displayStr =  '<table width="98%"><tr><td align="right" style="border-bottom:0px">
<img src = "/fs/graphics/closeMaginfier.jpg" οnclick="closeDiv(/''+displayName+'/',/''+displayIFrame+'/')">
</td></tr></table><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo"  
οnkeydοwn=" closeDiv(/''+displayName+'/',/''+displayIFrame+'/')">' + '<font class="sfont" color="red">沒有符合條件的記錄,點任意鍵返回</font>';
       displayAlert(displayStr);
       return;
   }
    var rows = dataText.split("<r>");    
    var _t=[];    
    var cols;
    var pos = "/'" + posNames + "/'";    
    
    for(var i = 0; i < rows.length; i++) {
        cols = rows[i].split("<c>");      
        values = "/'" ;
        valuesIndexArray = valueIndexs.split(",");
        for( j = 0; j < valuesIndexArray.length; j++)
        {
            var temp = cols[eval(valuesIndexArray[j])];
            //回填時把null置換成空字符串
            if(temp == 'null')
            {
                temp = '';
            }
            if(j < valuesIndexArray.length - 1)
            {
                values = values + temp + "<c>";
            }
            else
           {
               values = values + temp + "/'";
           }
        }  
        
        if(i == 0)
        {
           _t[i] = '<tr  class="maginfierBody" id = "'+maginfierName+'divrow0" οnmοuseοver="rollover(this)"
οnmοuseοut="rollout(this)" ><td width="5"  align="center">
<input type="radio" id="'+maginfierName+'rdo" name="rdo"  οnkeydοwn=" keyDowm('+i+', '+pos+', '+values+',/''+maginfierName+'/',/''+displayName+'/',/''+displayIFrame+'/');" ></td>';
        }
        else
        {
            _t[i] = '<tr class="maginfierBody" id = "'+maginfierName+'divrow'+i+'" οnmοuseοver="rollover(this)"
οnmοuseοut="rollout(this)"  ><td width="5"  align="center"><input type="radio" name="rdo"  οnkeydοwn=" keyDowm('+i+', '+pos+', '+values+',/''+maginfierName+'/',/''+displayName+'/',/''+displayIFrame+'/');" ></td>';
        }
        //根據表頭顯示相關數據    
        for(var j = 1 ; j < tableHead.length ; j++)
        {
            //在放大鏡表格顯示時,把null置換成空格顯示
            if(cols[j] == 'null')
            {
                cols[j] = " ";
            }
            _t[i] = _t[i] + '<td  οnclick="filled('+pos+', '+values+',/''+displayName+'/',/''+displayIFrame+'/')"><span class="rs">'+cols[j]+'</span></td>';
        }
        _t[i] = _t[i] + '</tr>';
        
    }  
    
     var tableHeadStr = addMaginfierHeader();
    
    displayStr =  '<table width="98%"><tr><td align="right" style="border-bottom:0px"><img src = "/fs/graphics/closeMaginfier.jpg" οnclick="closeDiv(/''+displayName+'/',/''+displayIFrame+'/')"></td></tr></table><table cellspacing="1" width="98%" cellpadding="1" class="ItemList">'+ tableHeadStr +_t.join('')+'</table> ';
    if(responseContent[1] != null)
    {
        pageParams = responseContent[1].split(",");
        prePageNo = parseInt(pageParams[2]) - 1;
        prePageFunction = maginfierFunction + "," +prePageNo+")";
        nextPageNo = parseInt(pageParams[2]) + 1;
        nextPageFunction = maginfierFunction + ", "+nextPageNo+")";
        
        displayStr += '<br> <a href="javascript:if('+prePageNo+' == 0){alert(/'已經是第一頁了/');}else{'+prePageFunction+'} ">上一頁</a>';
        displayStr += '<font class="sfont"> | 第'+pageParams[2]+'頁 | </font> ';
        displayStr += '<a href="javascript:if('+nextPageNo+' > '+pageParams[1]+'){alert(/'已經是最後一頁了/'); }else{'+nextPageFunction+'}">下一頁</a>';
        displayStr += '<font class="sfont"> | 共'+pageParams[1]+'頁 | 共'+pageParams[0]+'行</font>';      
    }
  
    displayMaginfier(displayStr);

}
function test()
{
    var a = '23,,,43,23';
    var b = a.split(",");
    alert(b.length);
}
function addMaginfierHeader()
{
    var tableHeadStr = '<tr class="maginfierTitle"><td width="5"  align="center" ></td>';
    for(i = 1 ; i < tableHead.length ; i++)
    {
        tableHeadStr = tableHeadStr + '<td align="center" >' + tableHead[i] + "</td>"
    }
    tableHeadStr = tableHeadStr + "</tr>";
    return tableHeadStr;
}
function displayAlert(displayStr)
{
    displayDiv = getElement(displayName);    
displayDiv.innerHTML = displayStr;
displayDiv.style.display='block';  

    IfrRef = getElement(displayIFrame);
IfrRef.style.width = displayDiv.offsetWidth;
    IfrRef.style.height = displayDiv.offsetHeight;
    IfrRef.style.top = displayDiv.style.top;
    IfrRef.style.left = displayDiv.style.left;
    IfrRef.style.zIndex = displayDiv.style.zIndex - 1;
    IfrRef.style.display = "block";

document.getElementById(maginfierName+"rdoAlert").checked = true;
document.getElementById(maginfierName+"rdoAlert").focus();
}
function displayMaginfier(displayStr)
{
    displayDiv = getElement(displayName);    
displayDiv.innerHTML = displayStr;
displayDiv.style.display='block';


    IfrRef = getElement(displayIFrame);
IfrRef.style.width = displayDiv.offsetWidth;
    IfrRef.style.height = displayDiv.offsetHeight;
    IfrRef.style.top = displayDiv.style.top;
    IfrRef.style.left = displayDiv.style.left;
    IfrRef.style.zIndex = displayDiv.style.zIndex - 1;
    IfrRef.style.display = "block";

document.getElementById(maginfierName+"divrow0").bgColor='#CCFF99';
document.getElementById(maginfierName+"rdo").checked = true;
document.getElementById(maginfierName+"rdo").focus();
}

/*具體放大鏡頁面處理方法*/
function handleStateChange() {    
    if(xmlHttp.readyState == 4) {
        if(xmlHttp.status == 200) {          
           responseDisplay();          
        }
    }
}
function initMaginfierParas(serverPath0, divName, iFrameName, posNames0, valueIndexs0, nextPos0)
{
    serverPath = serverPath0;
    displayName = divName;
    displayIFrame = iFrameName;
    posNames = posNames0;
    valueIndexs = valueIndexs0
    nextPos = nextPos0;
}

/*具體放大鏡JavaScript*/

//組織機構放大鏡
function orgMaginfier(serverPath0, divName, iFrameName, posNames0,valueIndexs0, nextPos0, orgCode, orgId, transTypeId, maginfierType, pageNo)
{    
initMaginfierParas(serverPath0, divName, iFrameName, posNames0, valueIndexs0, nextPos0);
maginfierName = 'OrgMaginfier' + divName;
maginfierFunction = "orgMaginfier(/'"+serverPath0+"/', /'"+divName+"/', /'"+iFrameName+"/', /'"+posNames0+"/',/'"+valueIndexs0+"/', /'"+nextPos0+"/', /'"+orgCode+"/', /'"+orgId+"/', /'"+transTypeId+"/', /'"+maginfierType+"/'";
    
    len = tableHead.length;
    tableHead.splice(0, len);
    tableHead[0] = "單位ID";
    tableHead[1] = "單位編號";
    tableHead[2] = "單位名稱";      
    tableHead[3] = "單位英文名稱";
    
    queryString = "maginfierClassName=OrgMaginfier&orgCode="+orgCode+"&orgId="+orgId+"&maginfierType="+maginfierType+"&transTypeId="+transTypeId+"&pageNo="+pageNo;
    
  operationRequest(queryString);
}



3.1.1.2       Css文件內容:

/* 界面樣式 */

.termFrame{

       width:298px !important;

       width:500px;

       overflow:auto;

       height:360px;

       scrollbar-face-color: #FFFFCC; scrollbar-shadow-color: #FFFFCC; scrollbar-highlight-color: #FFFFCC; scrollbar-3dlight-color: #FFFFCC;  scrollbar-darkshadow-color: #6699CC; scrollbar-track-color: #FFFFCC; scrollbar-arrow-color: #99CCFF;

    

       margin-top:1px !important;

       margin-top:0;  

       border:1px solid #999999;

       background-color:#FFFFFF;

       position:absolute;

       cursor:hand;

       padding:2px;

       font-size:70%;

       z-index:100

       }

       .maginfierTitle {

BORDER-RIGHT: 1px; BORDER-TOP: 1px;BORDER-LEFT: 1px; BORDER-BOTTOM: 1px;BACKGROUND-COLOR: #456795; color: #FFFFFF;

}

       .maginfierBody {

        BORDER-RIGHT: 1px;BORDER-TOP: 1px;BORDER-LEFT: 1px;BORDER-BOTTOM: 1px;

}


3.1.2   當點擊查詢助手圖標時(例如查詢組織機構):
function orgMaginfier(serverPath0, divName, iFrameName, posNames0,valueIndexs0, nextPos0, orgCode, orgId, transTypeId, maginfierType, pageNo)

{    

       initMaginfierParas(serverPath0, divName, iFrameName, posNames0, valueIndexs0, nextPos0);

       maginfierName = 'OrgMaginfier' + divName;      

       maginfierFunction = "orgMaginfier(/'"+serverPath0+"/', /'"+divName+"/', /'"+iFrameName+"/', /'"+posNames0+"/',/'"+valueIndexs0+"/', /'"+nextPos0+"/', /'"+orgCode+"/', /'"+orgId+"/', /'"+transTypeId+"/', /'"+maginfierType+"/'";

    

    len = tableHead.length;

    tableHead.splice(0, len);

    tableHead[0] = "單位ID";

    tableHead[1] = "單位編號";

    tableHead[2] = "單位名稱";      

    tableHead[3] = "單位英文名稱";

    

    queryString = "maginfierClassName=OrgMaginfier&orgCode="+orgCode+"&orgId="+orgId+"&maginfierType="+maginfierType+"&transTypeId="+transTypeId+"&pageNo="+pageNo;

    

  operationRequest(queryString);

}

3.1.3   Js中的處理請求的函數
function operationRequest(queryString, postBlock) {  

    

    var url = serverPath + "/AjaxMaginfier?" +  queryString;

    

    createXMLHttpRequest();

    xmlHttp.onreadystatechange = handleStateChange;

    xmlHttp.open("POST", url, true);    

  //    postBlock = "獲得界面元素";

  //設置大塊數據傳輸postBlock,這樣可以解決大數據量傳向後臺。

    xmlHttp.send(postBlock);

}


3.1.4   當數據傳回前臺後
//該函數的名稱不要改變,因爲我在js文件中決定了用該函數來處理傳回的數據

function handleStateChange() {    

    if(xmlHttp.readyState == 4) {

        if(xmlHttp.status == 200) {          

           responseDisplay();          

        }

    }

}


3.1.5   具體處理傳回的數據:
function responseDisplay() {       

    var responseText = xmlHttp.responseText;

    var responseContent = responseText.split("|");

    var dataText = responseContent[0];

   if(dataText.length == 0)

   {

       var displayStr = rightSpace + '<img src = "/fs/graphics/closeMaginfier.jpg" οnclick="closeDiv(/''+displayName+'/',/''+displayIFrame+'/')"><br><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo"  οnkeydοwn=" closeDiv(/''+displayName+'/',/''+displayIFrame+'/')">' + '<font class="sfont" color="red">沒有符合條件的記錄,點任意鍵返回</font>';

       displayAlert(displayStr);

       return;

   }

    var rows = dataText.split(";");    

    var _t=[];    

    var cols;

    var pos = "/'" + posNames + "/'";    

    

    for(var i = 0; i < rows.length; i++) {

        cols = rows[i].split(",");      

        values = "/'" ;

        valuesIndexArray = valueIndexs.split(",");

        for( j = 0; j < valuesIndexArray.length; j++)

        {

            var temp = cols[eval(valuesIndexArray[j])];

            //回填時把null置換成空字符串

            if(temp == 'null')

            {

                temp = '';

            }

            if(j < valuesIndexArray.length - 1)

            {

                values = values + temp + ",";

            }

            else

           {

               values = values + temp + "/'";

           }

        }  

        

        if(i == 0)

        {

           _t[i] = '<tr  class="maginfierBody" id = "'+maginfierName+'divrow0" οnmοuseοver="rollover(this)" οnmοuseοut="rollout(this)" ><td width="5"  align="center"><input type="radio" id="'+maginfierName+'rdo" name="rdo"  οnkeydοwn=" keyDowm('+i+', '+pos+', '+values+',/''+maginfierName+'/',/''+displayName+'/',/''+displayIFrame+'/');" ></td>';

        }

        else

        {

            _t[i] = '<tr class="maginfierBody" id = "'+maginfierName+'divrow'+i+'" οnmοuseοver="rollover(this)" οnmοuseοut="rollout(this)"  ><td width="5"  align="center"><input type="radio" name="rdo"  οnkeydοwn=" keyDowm('+i+', '+pos+', '+values+',/''+maginfierName+'/',/''+displayName+'/',/''+displayIFrame+'/');" ></td>';

        }

        //根據表頭顯示相關數據    

        for(var j = 0 ; j < tableHead.length ; j++)

        {

            //在查詢助手錶格顯示時,把null置換成空格顯示

            if(cols[j] == 'null')

            {

                cols[j] = " ";

            }

            _t[i] = _t[i] + '<td  οnclick="filled('+pos+', '+values+',/''+displayName+'/',/''+displayIFrame+'/')"><span class="rs">'+cols[j]+'</span></td>';

        }

        _t[i] = _t[i] + '</tr>';

        

    } //顯示錶頭內容

function addMaginfierHeader()

{

    var tableHeadStr = '<tr class="maginfierTitle"><td width="5"  align="center" ></td>';

    for(i = 0 ; i < tableHead.length ; i++)

    {

        tableHeadStr = tableHeadStr + '<td align="center" >' + tableHead[i] + "</td>"

    }

    tableHeadStr = tableHeadStr + "</tr>";

    return tableHeadStr;

}

//如果未查詢到紀錄,顯示提示信息

function displayAlert(displayStr)

{

    _termFrame=getElement(displayName);

    

       _termFrame.innerHTML = displayStr;

       // 顯示結果

      

       _termFrame.style.display='block';

      

       IfrRef = getElement(displayIFrame);

       IfrRef.style.width = _termFrame.offsetWidth;

    IfrRef.style.height = _termFrame.offsetHeight;

    IfrRef.style.top = _termFrame.style.top;

    IfrRef.style.left = _termFrame.style.left;

    IfrRef.style.zIndex = _termFrame.style.zIndex - 1;

    IfrRef.style.display = "block";

      

       document.getElementById(maginfierName+"rdoAlert").checked = true;

      

       document.getElementById(maginfierName+"rdoAlert").focus();

      

}

//顯示查詢助手

function displayMaginfier(displayStr)

{

    _termFrame=getElement(displayName);

    

       _termFrame.innerHTML = displayStr;

       // 顯示結果

       _termFrame.style.display='block';

       //setHidden(overlaySelEles);

       //_termFrame.style.visibility="visible";

       IfrRef = getElement(displayIFrame);

       IfrRef.style.width = _termFrame.offsetWidth;

    IfrRef.style.height = _termFrame.offsetHeight;

    IfrRef.style.top = _termFrame.style.top;

    IfrRef.style.left = _termFrame.style.left;

    IfrRef.style.zIndex = _termFrame.style.zIndex - 1;

    IfrRef.style.display = "block";

      

       document.getElementById(maginfierName+"divrow0").bgColor='#CCFF99';

       document.getElementById(maginfierName+"rdo").checked = true;

      

       document.getElementById(maginfierName+"rdo").focus();

}


3.2    Servlet後臺
選擇Servlet作爲後臺,是因爲如果採用Struts Action爲後臺處理程序,則必須指定要返回的頁面。而使用Servlet則沒有這個要求。默認返回到請求頁面。而這個查詢助手Servlet接受所有的查詢助手請求,根據前臺傳來的查詢助手實現類名稱參數,由Spring創建查詢助手實現類對象,該對象實現了查詢助手接口(MaginfierInterface),從而獲取返回值文本。返回到前臺。

3.2.1   具體代碼如下:

3.2.1.1       查詢助手Servlet
public void doGet(HttpServletRequest request, HttpServletResponse response)

                     throws ServletException, IOException {

              String maginfierClassName = request.getParameter("maginfierClassName");            

              MaginfierFactory factory = MaginfierFactory.getInstance();

              MaginfierInterface maginfier = factory.createMaginfier(maginfierClassName);

        String ret =  maginfier.getReturnValue(request);

        System.out.println("ret = " + ret);

              response.setContentType("text/xml;charset=GBK");

              PrintWriter out = response.getWriter();

                            

              out.write(ret);

              

              out.close();

       }


3.2.1.2       Web.xml配置
3.2.1.2.1      在Web.xml中配置查詢助手Servlet
<servlet>

        <servlet-name>AjaxMaginfier</servlet-name>

        <servlet-class>com.iss.fs.web.module.example.AjaxMaginfier</servlet-class>

        <!—在系統初次啓動時,初始化1次-->        

        <load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

        <servlet-name>AjaxMaginfier</servlet-name>

        <url-pattern>/AjaxMaginfier</url-pattern>

</servlet-mapping>


3.2.1.3       查詢助手具體實現類
3.2.1.3.1      實現查詢助手接口方法
public class CurrencyMaginfier implements MaginfierInterface

{

       public String getReturnValue(HttpServletRequest request)

       {

              List list = null;

              StringBuffer results = new StringBuffer();

              CurrencyDAO dao = new CurrencyDAO();

              String currencyAbbrName = request.getParameter("currencyAbbrName");

              String responsibilityId = request.getParameter("responsibilityId");

              if(currencyAbbrName == null || currencyAbbrName.equals("") || currencyAbbrName.equals("undefined"))

              {

                     currencyAbbrName = "";

              }

              if(responsibilityId == null || responsibilityId.equals("") || responsibilityId.equals("undefined"))

              {

                     responsibilityId = "-1";

              }

              try

              {

                     list = dao.getMaginfierResults(currencyAbbrName, responsibilityId);

                    

              }

              catch (Exception ex)

              {

                     ex.printStackTrace();

              }

              if (list != null)

              {

                     Currency currency = null;                  

                     for(int i = 0 ; i < list.size(); i++)

                     {

                            currency = (Currency)list.get(i);

                            results.append(currency.getID()).append(",");

                            results.append(currency.getCurrencyAbbrName()).append(",");

                            results.append(currency.getCurrencyName());                          

                            if(i < (list.size() - 1))

                            {

                                   results.append(";");

                            }

                     }

              }

              return results.toString();

       }

}


3.3    技術難點解析
3.3.1   查詢助手函數參數設計:
固定參數:serverPath, divName, iFrameName, posNames,valueIndexs, nextPos

serverPath:表示webserver的地址,如:/myapp

divName:顯示選擇界面的Div名稱

iFrameName:顯示選擇界面的Ifranme名稱,因爲IE的缺陷,div顯示時不能覆蓋下面的選擇框,所以我們使用Iframe作爲div的底板。

posNames:選擇紀錄後回顯的頁面元素,如:orgId,orgName,orgCode

valueIndexs:對應回顯頁面元素,紀錄的列序號,如 0,2,1

nextPos:選擇結束後要把輸入焦點,移動到下一個頁面元素名稱

固定參數後面的參數,不同的查詢助手有不同參數列表,主要是條件數據。

3.3.2   查詢助手選擇界面的表頭設計:
不同的查詢助手選擇界面有不同的表頭,我們使用js的全局數組變量來存儲,每個查詢助手使用前都先清空表頭數組,使用splice(0, len)

len = tableHead.length;

    tableHead.splice(0, len);    

    tableHead[0] = "外部賬戶ID";

    tableHead[1] = "外部賬戶編號";

    tableHead[2] = "外部賬戶名稱";

    tableHead[3] = "外部銀行名稱";

    tableHead[4] = "機構號";

    tableHead[5] = "聯行號";


顯示錶頭:

var tableHeadStr = '<tr class="maginfierTitle"><td width="5"  align="center" ></td>';

    for(i = 0 ; i < tableHead.length ; i++)

    {

        tableHeadStr = tableHeadStr + '<td align="center" >' + tableHead[i] + "</td>"

    }

tableHeadStr = tableHeadStr + "</tr>";


3.3.3   處理後臺傳來的數據:
3.3.3.1.1      接受數據:
var responseText = xmlHttp.responseText;


3.3.3.1.2      查詢無紀錄處理:
if(responseText.length == 0)

   {

       var displayStr = rightSpace + '<img src = "/fs/graphics/closeMaginfier.jpg" οnclick="closeDiv()"><br><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo"  οnkeydοwn=" closeDiv()">' + '<font class="sfont" color="red">沒有符合條件的記錄,點任意鍵返回</font>';

       displayAlert(displayStr);

       return;

   }


Onkeydown表示響應任意鍵,則關閉查詢助手選擇界面。

Onclick 表示響應鼠標點擊

3.3.3.1.3      顯示查詢結果:
因爲我們在後臺把查詢數據封裝成文本傳回前臺,所以到前臺後要解析文本,我不使用xml文本,數據封裝規則是紀錄間用“;”隔離,列之間用“,”隔離。同樣到前臺後使用相同的規則解析數據。

把文本數據分成若干行數據

var rows = responseText.split(";");


3.4    總結
Ajax實現查詢助手功能是Ajax在項目中實戰的一個小小的例子,根據以後的研發,將會產生更多更好的應用,本人在文檔的Ajax簡介部分引用了別的文檔的說明,在查詢助手的實現中借鑑了Google的Suggest設計理念,Suggest實現是直接從後臺傳來表格Frame,後臺定義顯示邏輯,在查詢助手的設計中,前臺來決定顯示邏輯,後臺僅提供數據,實現數據和顯示的分離,這樣就會造成前臺需要解析數據文本,處理顯示邏輯的Javascript函數,顯得前臺的JavaScript比較多,但我認爲這是可以接受的,因爲Ajax主要是前臺邏輯。另外,Ajax查詢助手的後臺實現採用了Spring Bean管理容器,只是爲了後期擴展的方便性,藉助Spring容器管理的強大功能,實現類似工廠模式的功能。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章