Ajax 是用javascript和DOM,XML实现的web客户端与服务器端的异步通讯技术。 不是什么新东西,老技术,新面孔而已。 对于构建类似桌面应用的web程序来说,Ajax无疑是有效的工具, 处理强交互性做得很突出。 Google是Ajax的先行者, 大名鼎鼎的Google Map则是Ajax的优秀作品。 相信Ajax的广泛运用将进一步改变web程序的面孔,同时过去被认为只有桌面程序更加能满足要求的构架方案如今Ajax可以成为另一种不错的选择。桌面程序则再次面临市场萎缩,与此同时b/s在继续拓宽其领地。 Ajax不是什么新技术, 只要客户端的浏览器支持javascript,支持dom就能完成Ajax的核心工作之一, 而服务器端代码你可以选择3p技术的任何一种, 是极其自由的。以前的web聊天程序, 你或许要常常刷新页面来获知你是否有了新的消息,而一次刷新则意味着一次和页面载入,这显然不符合即时通讯的要求,在这里Ajax则有了发挥的空间,这是我为什么选择它的原因。 如果你熟悉Ajax, 请允许我上面说了这么多废话,因为我无法保证每个读者都熟悉它。当然不乏精通人士,敬请纠正我的错误,如果存在的话。 现在我将发布我的Ajax作品。 请不要误以为我在炫耀什么,这并不是什么高级的作品,事实上我只是想发布它,因为很长时间我的blog没有更新了,当然如果我的行为对你的进步产生了影响,那将会使我感觉到快乐。最后要说的是, 著作权,中国人不太重视这个, 我想说的是,不管这个作品品质如何,只要它是出自某个人辛苦的劳作而且未将它授权给别人,那它就属于作者, 你需要适当限制发生作者不愿看到的行为,特别是商业目的。在这个实例当中客户端我使用了ms的浏览器, 服务器端则采用ms的 jscript一共7个程序文件Ajax.js : Ajax程序的中心库,我希望这是一个通用框架的核心组成部分AjaxApp.js : 本程序响应服务器异步通讯的代码, 负责本程序客户端的大部分工作frmInpCheck.js: 表单输入的控制模块pageCtl.js: 页面元素的控制模块, 集中体现Ajax中DOM的运用util.js: 其他工具模块web-sgn.asp: 客户端页面代码,利用Ajax交互的页面web-server-sgn.asp: 服务器的后端代码,Ajax通讯的服务端还需指出的是 Ajax名义上是需要利用xml格式进行数据双端交付的。本程序并没有体现这点, 但丝毫未影响Ajax的正常工作,我采用了某种常规的替代方法。 访问体验本程序最新 v1.4 版: http://www.v8v.com.cn/_sgpro/web-sgn/web-sgn.asp 运行效果图: v1.42 效果图 以下是v1.0的全部源代码://Copyright (C) 2007-11 sgpro//程序:Ajax.js //建立xmlHttpRequest对象 var globalXmlHttp = false; function CreateXMLHttp() { try { //alert("create activeX"); globalXmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { globalXmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e2) { globalXmlHttp = false; } } //alert("create activeX success"); return globalXmlHttp; } function nonAjaxTrans() { return typeof(globalXmlHttp) == 'boolean' && globalXmlHttp == false; } //Ajax传送, text方式 function AjaxTransText(sUrl, funcCallClient) { if (nonAjaxTrans()) { if ( typeof(CreateXMLHttp()) != 'object') { return false; } } globalXmlHttp.open("GET", sUrl, true); globalXmlHttp.onreadystatechange = funcCallClient; globalXmlHttp.send(null); } //Ajax传送, xml方式 function AjaxTransXML(sUrl, xml, funcCallClient) { alert("sUrl:" + sUrl + "\nxml:" + xml + "\nfunc:" + funcCallClient); if (nonAjaxTrans()) { if ( typeof(CreateXMLHttp()) != 'object') { return false; } } globalXmlHttp.open("POST", sUrl, true); globalXmlHttp.setRequestHeader("Content-Type", "text/xml"); globalXmlHttp.onreadystatechange = funcCallClient; globalXmlHttp.send(xml); } //获取Ajax连接对象的状态 function getAjaxTransState() { if (!nonAjaxTrans()) { return globalXmlHttp.readyState; } return false; } function ajaxTransReady() { if (!nonAjaxTrans()) { if (globalXmlHttp.readyState == 4 && globalXmlHttp.status == 200 ) { return true; } } return false; } //获取Ajax返回文本 function getAjaxTransResultText() { if (ajaxTransReady()) { //alert(globalXmlHttp.responseText); return globalXmlHttp.responseText; } } //获取Ajax返回xml function getAjaxTransResultXML() { if (ajaxTransReady()) { return globalXmlHttp.responseXML; } } function cleanAjax() { globalXmlHttp = false; } //程序:AjaxApp.js var globalUrl = "web-server-sgn.asp"; var globalSelectUser; function AjaxTextDispatch(procName) { var ajaxUrl; var ajaxHandle; //alert(procName); ajaxUrl = globalUrl + "?func=" + procName; switch (procName ) { case "logout": if (frmLogin.username.value == "") { return; } ajaxUrl = ajaxUrl + "&username=" + frmLogin.username.value; ajaxHandle = logout; break; case "login": res.innerText='请稍候...'; if (!checkNotNull(frmLogin)) { return false; } ajaxUrl = ajaxUrl + "&username=" + frmLogin.username.value + "&password=" + frmLogin.password.value; ajaxHandle = login; break; case "register": if (!checkNotNull(frmLogin)) { return false; } document.getElementById("res").innerText='请稍候...'; ajaxUrl = ajaxUrl + "&username=" + frmLogin.username.value + "&password=" + frmLogin.password.value; ajaxHandle = register; break; case "getUserList": ajaxHandle = getUserList; break; case "receiveMessage": ajaxUrl = ajaxUrl + "&FromUser=" + frmMessage.ToUser.value + "&ToUser=" + frmMessage.FromUser.value; ajaxHandle = receiveMessage; break; case "sendMessage": if (!checkNotNull(frmMessage)) { return false; } if (frmMessage.ToUser.value=="") { alert("请选择联系人..."); UserListBlock.UserList.focus(); return false; } ajaxUrl = ajaxUrl + "&FromUser=" + frmMessage.FromUser.value + "&ToUser=" + frmMessage.ToUser.value + "&Message=" + frmMessage.Message.value; ajaxHandle = sendMessage; break; } //alert(ajaxUrl); AjaxTransText(ajaxUrl, ajaxHandle); } function login() { if (!ajaxTransReady()) { return; } var ret = getAjaxTransResultText(); if (ret == "") { ret="连接失败"; } if (ret == "False") { ret = "用户或密码无效"; alert(ret); } else { alert("登陆成功"); document.frmLogin.style.display = "none"; UserListBlock.style.display="block"; document.frmMessage.style.display = "block"; document.frmMessage.FromUser.value = frmLogin.username.value; AjaxTextDispatch('getUserList'); freshInputing(); ListenMessage(); } document.getElementById("res").innerHTML ="<font color=red> " + ret + "</font>"; return; } function getUserList() { //var nodesNum = frmMessage.ToUser.childNodes.length; //alert("Nodes:" + frmMessage.ToUser.childNodes.length); //for (var i=0; i < nodesNum - 1; i++) //{ // document.frmMessage.ToUser.removeChild(frmMessage.ToUser.childNodes[i]); //} if (!ajaxTransReady()) { return; } globalSelectUser = UserListBlock.UserList.value; UserListBlock.UserList.innerHTML = ""; var ret = getAjaxTransResultText(); var str = new String(ret); var uls = str.split("<br>"); var utext=""; for( var i =0; i < uls.length-1; i++) { var op = document.createElement("option"); var str2 = new String(uls[i]); op.value=str2.split("|")[0]; op.innerHTML = str2.split("|")[0]; op.innerText = str2.split("|")[0] + (str2.split("|")[1] == "true"? " (联机)":" (脱机)"); op.statu = str2.split("|")[1]; UserListBlock.UserList.appendChild(op); } RefreshOnline(); } function register() { if (!ajaxTransReady()) { return; } var ret=getAjaxTransResultText(); if (ret == "") { ret="连接失败"; } if (ret == "False") { ret = "The user '" + frmLogin.username.value + "' had been used"; alert(ret); } else { ret = "Register success"; if (confirm("注册成功,现在就登录吗?") == true) { login(); } } document.getElementById("res").innerHTML ="<font color=red> " + ret + "</font>"; return; } function logout() { if (!ajaxTransReady()) { return; } var ret=getAjaxTransResultText(); if (ret == "") { ret="连接失败"; } if (ret == "False") { ret = frmLogin.username.value + " 未能成功注销!"; } else { ret = frmLogin.username.value + " 已经退出"; } } function receiveMessage() { if (!ajaxTransReady()) { return; } var ret=getAjaxTransResultText(); //alert(ret); if (ret == "") { ret="连接失败"; } if (ret == "false") { window.title= "无消息"; res.innerHTML="<font color=red> " + ret + "</font>"; } else { var str = new String(ret); var strArr = str.split("<br>"); var listt = ""; //alert(strArr); for ( i = 0; i < strArr.length-1; i++) { var str2 = new String(strArr[i]); t = str2.split("|")[0]; //时间 f = str2.split("|")[1]; //from m = str2.split("|")[2]; //msg //listt = t + " " + f + "说:\r\n " + m + "\r\n"; listt = f + " 说 (" + t + ")\r\n " + m + "\r\n"; frmMessage.panel.value = frmMessage.panel.value + listt; scrollToPanelBottom(); } } AjaxTextDispatch('getUserList'); timerOut=window.setTimeout("AjaxTextDispatch('receiveMessage')",1000); } function sendMessage() { if (!ajaxTransReady()) { return; } var ret=getAjaxTransResultText(); if (ret == "") { ret="连接失败"; } if (ret == "False") { ret = "发送失败"; res.innerHTML="<font color=red> " + ret + "</font>"; } else { var msgtxt = frmMessage.FromUser.value + " 说 (" + GetNow() + ") \r\n " + frmMessage.Message.value + "\r\n"; frmMessage.panel.value = frmMessage.panel.value + msgtxt; } scrollToPanelBottom(); frmMessage.Message.value = ""; frmMessage.Message.focus(); } //程序:pageCtl.js function ListenMessage() { window.ListenTimer = setTimeout("AjaxTextDispatch('receiveMessage')",1000); } function selectUser() { frmMessage.ToUser.value= UserListBlock.UserList.value; UserListBlock.style.display = "block"; frmMessage.style.display = "block"; frmMessage.FromUser.disabled = false; if ( frmMessage.FromUser.value == frmMessage.ToUser.value) { document.getElementById("tip").innerHTML = "<font color='red'>请问" + frmMessage.FromUser.value + "同志: <br>您不觉得和自己聊天是对您的智商的一种侮辱吗?<br>我们试图纠正您的失误并且作出了某种限制。</font>"; frmMessage.Message.disabled=true; } else { document.getElementById("tip").innerText= frmMessage.FromUser.value + " 与 " + frmMessage.ToUser.value + " 聊天中" frmMessage.Message.disabled=false; frmMessage.Message.focus(); } } function RefreshOnline() { for (var i=0; i < UserListBlock.UserList.childNodes.length; i++) { var op = UserListBlock.UserList.childNodes[i]; if (op.value == globalSelectUser) { op.selected="true"; break; } } } function scrollToPanelBottom() { frmMessage.panel.scrollTop=frmMessage.panel.scrollHeight; } function ChangeGlobalValue() { globalSelectUser = UserListBlock.UserList.value; } function sendByShortCut() { if (event.keyCode == 13) { document.getElementById("btnSend").click(); return false; } else { freshInputing(); return true; } } function freshInputing() { var Reg = new RegExp("\r\n", "g"); frmMessage.Message.value = frmMessage.Message.value.replace(Reg, ""); document.getElementById("btnSend").disabled= (frmMessage.Message.value == ""); } //程序:util.js function GetNow() { return FormatDateTime(""); } function FormatDateTime(date) { var dat; if (date == "" || date == null) { dat = new Date(); } else { dat = new Date(date); } var y = dat.getYear(); var m = parseInt(dat.getMonth())+1 var d = dat.getDate(); var h = dat.getHours(); var min = dat.getMinutes(); var s = dat.getSeconds(); var strDateTime = y + "-" + m + "-" + d + " " + h + ":" + min + ":" + s; return strDateTime; }//程序:web-sgn.asp<%@language='javascript'%><html> <head> <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=gb2312"> <title>web sgn</title> </head> <script src="util.js"></script> <script src="frmInpCheck.js"></script> <script src="pageCtl.js"></script> <script src="Ajax.js"></script> <script src="AjaxApp.js"></script> <script language="javascript"> </script> <body onunload="AjaxTextDispatch('logout')"> <table align="center" valign="top" bgcolor="#dddddd" border=1 cellspacing="0" cellpadding="0"> <tr> <td> <form name="frmLogin" id="frmLogin" action="web-server-sgn.asp" method="post" onsubmit="return checkNotNull(this);"> 用户:<input type="text" name="u" id="username" NotNull="true" tag="用户名"><br> 密码:<input type="password" name="p" id="password" NotNull="true" tag="密码"><br> <button onclick="AjaxTextDispatch('login')" >登陆</button> <button onclick="AjaxTextDispatch('register')" >注册</button> <input type="submit" value="同步登陆"> <input type="hidden" id="func" name="func" value="login"> <div id="res" name="res"></div> </form> </td> </tr> <tr> <td valign="top" align="center"> <form id="UserListBlock" name="UserListBlock" style="display:none;"> <br><center><div id="tip" style="font-size:28;font-family:'黑体';"> 双击选择下面的联系人聊天</div></center><br> <select name="UserList" id="UserList" size="8" MULTIPLE style="width:200;border:inset 2px;" ondblclick="selectUser()" onclick="ChangeGlobalValue()"></select> </form> </td> </tr> <tr> <td> <form name="frmMessage" id="frmMessage" action="web-server-sgn.asp" method="post" style="display:none;" onsubmit="return checkNotNull(this);"> <textarea name="panel" id="panel" ="scrollToPanelBottom()" style="font-size:12;font-weight:1;color:#ffff33;width:660;border:inset 2px ; background-color : #7777ff; text-left-padding:10px;" rows="20" readonly NotNull="false" tag="消息"></textarea><br> <textarea name="Message" id="Message" width="570" NotNull="true" tag="消息" disabled="true" rows="4" cols="70" multiple style="border:inset 1px #777777;" onkeydown="sendByShortCut()" onkeyup="freshInputing()"></textarea> <button id="btnSend" onclick="AjaxTextDispatch('sendMessage')" style="width:70;height:70;" >发送消息</button> <input type="button" value=" 注 销 " onclick="window.location=location.href;" style="width:70;height:70;border: dashed 1px;"> <input type="hidden" id="func" name="func" value="sendMessage"> <input type="hidden" id="FromUser" name="FromUser" value=""> <input type="hidden" id="ToUser" name="ToUser" > <!--<div id="online"></div>--> </form> </td> </tr> </table> </body></html>//程序:Web-server-sgn.asp<%@language="javascript"%> <% function GetNow() { return FormatDateTime(""); } function FormatDateTime(date) { var dat; if (date == "" || date == null) { dat = new Date(); } else { dat = new Date(date); } var y = dat.getYear(); var m = parseInt(dat.getMonth())+1 var d = dat.getDate(); var h = dat.getHours(); var min = dat.getMinutes(); var s = dat.getSeconds(); var strDateTime = y + "-" + m + "-" + d + " " + h + ":" + min + ":" + s; return strDateTime; } var conn; function DbConnect(strPath, strUser, strPass) { try { var connstr = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + Server.MapPath(strPath) + ";" + "User Id=" + strUser + ";" + "Password=" + strPass + ";" conn = Server.CreateObject("ADODB.Connection"); conn.Open(connstr); return true; } catch (e) { Response.Write("<center><h1><b><font color = red>Db Connection Error:" + connstr + "</h3></font></b>"); return false; } } function DbExecute(StrSqlStatement) { try { var rs = conn.Execute(StrSqlStatement); } catch ( e) { Response.Write("<center><h1><b><font color = red>Db Execute Error:"+e.message + "<br>"); Response.Write(StrSqlStatement + "</h3></font></b>"); debugger; return false; } return rs; } function DbCollect() { try { var rs = conn.close(); } catch ( e) { Response.Write("<center><h1><b><font color = red>:Db Collect Error: "+e.message + "<br>"); Response.End(); } return rs; } function sendMessage(strDateTime, strFromUser, strToUser, strMessage) { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } var strSql = " INSERT INTO Message(msgtime, userfrom, userto, msgtext, hasread) VALUES( '" + strDateTime + "','" + strFromUser + "','" + strToUser + "', '" + strMessage + "'," + " false) "; var ret = DbExecute(strSql); return typeof(ret) != 'False'; } function receiveMessage(strFromUser, strToUser) { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } var ret = ""; var strWhere = " WHERE userto = '" + strToUser + "' AND hasread = false" var strSql = " SELECT * FROM Message " + strWhere; var rs= DbExecute(strSql); while (!rs.Eof) { ret = ret + FormatDateTime(rs("msgtime")) + "|" + rs("userfrom") + "|" + rs("msgtext"); ret = ret + "<br>"; rs.MoveNext(); } rs.close(); var strUpd = "UPDATE Message SET hasread = true " + strWhere; DbExecute(strUpd); return ret; } function register(strUserName, strPassword) { if (VerifyUser(strUserName, strPassword, false)) { return false; } var strSql = " INSERT INTO [user](username, [password], online) VALUES ( '" + strUserName + "','" + strPassword + "', false) "; var ret = DbExecute(strSql); return typeof(ret) != 'False'; } function getUserList() { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } var strSql = " SELECT * FROM [user] order by online, [username]"; var rs= DbExecute(strSql); return rs; } function VerifyUser(strUserName, strPassword, blnCheckPassword) { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } var strSql = " SELECT * FROM [user] WHERE username='" + strUserName + "'" if (blnCheckPassword == true) { strSql = strSql + " AND [password]='" + strPassword + "'"; } var rs= DbExecute(strSql); return !rs.Eof; } function login(strUserName, strPassword) { if (VerifyUser(strUserName, strPassword, true)) { return setOnlineStatus(strUserName, true); } else { return false; } } function logout(strUserName) { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } return setOnlineStatus(strUserName, false); } function setOnlineStatus(strUserName, blnStatus) { if (conn == undefined) { DbConnect(Server.MapPath("chartdb.mdb"), "",""); } var strUpd = "UPDATE [user] SET online = " + blnStatus + " WHERE username='" + strUserName + "'"; var ret = DbExecute(strUpd); return typeof(ret) != 'False'; } var func = Request("func"); if (func == undefined || func== Request("null")) { func=""; } Response.charset = "GB2312"; DbConnect("chartdb.mdb", "",""); if (func == "sendMessage") { var result = sendMessage(GetNow(), Request("FromUser"), Request("ToUser"), Request("Message")); Response.write(result); } else if (func == "receiveMessage") { var rs = receiveMessage(Request("FromUser"), Request("ToUser")); if (rs=="") { rs = "false"; } Response.write(rs); } else if (func == "getUserList") { var rsu = getUserList(); if (typeof(rsu) != false) { while (!rsu.Eof) { Response.write(rsu("username") + "|" + rsu("online")); Response.write("<br>"); rsu.MoveNext(); } } rsu.close(); } else if (func == "login") { var rs = login(Request("username"), Request("password")); Response.write(rs); } else if (func == "logout") { var rs = logout(Request("username")); Response.write(rs); } else if (func == "register") { var rs = register(Request("username"), Request("password")); Response.write(rs); } else { Response.write("Parameters Error func='" + func +"'"); } DbCollect();%> //Copyright (C) 2007-11 sgpro 版本陆续升级中。。。 版本履历 v1.0功能: 注册,登录,注销,发送消息,接受消息,声音提示,实时更新用户列表和状态 v1.1功能: (新增)加载消息历史记录 v1.2功能: (新增)收发即时动作(如***正在输入消息)(新增)支持可视化元素传输如图片,链接,多媒体等。(修改)Ajax内核采用同步请求组 v1.21功能: (修改)Ajax内核增强请求队列组 (修改)Ajax错误处理能力(修改)用户表修改,增强用户信息处理(登录次数,登录ip等) v1.3功能: (新增) 收发闪屏震动(新增) 收发表情(新增) 字体选择,字体颜色,大小,样式编辑(新增) 掉线自动重连 (新增) 工具箱(修改)Ajax内核增强(修改)更改页面布局,页面样式 v1.4功能: (新增)好友管理(发出请求,处理验证,添加好友) (修改)Ajax内核增强请求队列错误的滞后排空 (修改) Ajax请求加入时间戳标识,排除重复取缓存问题

评论