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" onclick="closeDiv(\''+displayName+'\',\''+displayIFrame+'\')"></td></tr></table><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo" onkeydown=" 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" onmouseover="rollover(this)" onmouseout="rollout(this)" ><td width="5" align="center"><input type="radio" id="'+maginfierName+'rdo" name="rdo" onkeydown=" keyDowm('+i+', '+pos+', '+values+',\''+maginfierName+'\',\''+displayName+'\',\''+displayIFrame+'\');" ></td>';
}
else
{
_t[i] = '<tr class="maginfierBody" id = "'+maginfierName+'divrow'+i+'" onmouseover="rollover(this)" onmouseout="rollout(this)" ><td width="5" align="center"><input type="radio" name="rdo" onkeydown=" 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 onclick="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" onclick="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" onclick="closeDiv(\''+displayName+'\',\''+displayIFrame+'\')"><br><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo" onkeydown=" 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" onmouseover="rollover(this)" onmouseout="rollout(this)" ><td width="5" align="center"><input type="radio" id="'+maginfierName+'rdo" name="rdo" onkeydown=" keyDowm('+i+', '+pos+', '+values+',\''+maginfierName+'\',\''+displayName+'\',\''+displayIFrame+'\');" ></td>';
}
else
{
_t[i] = '<tr class="maginfierBody" id = "'+maginfierName+'divrow'+i+'" onmouseover="rollover(this)" onmouseout="rollout(this)" ><td width="5" align="center"><input type="radio" name="rdo" onkeydown=" 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 onclick="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" onclick="closeDiv()"><br><input type="radio" id="'+maginfierName+'rdoAlert" name="rdo" onkeydown=" 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
容器管理的强大功能,实现类似工厂模式的功能。
努力,在于我热爱我的事业,与中国的软件一起走向成熟,走向世界。
联系作者:
lijj_72@hotmail.com