techsir 登陆 |注册|TS首页
  首页 快活林 猿氏悟语

DISCUZ架构:AJAX之ajax.js 函数

By: 盖茨 发表于 2008-11-7 11:42:59 · 10622次点击   回复:2   
以下为引用的内容:
var Ajaxs = new Array();
function Ajax(recvType, statusId) {
        var aj = new Object();
        aj.statusId = statusId ? document.getElementById(statusId) : null;
        aj.targetUrl = '';
        aj.sendString = '';
        aj.recvType = recvType ? recvType : 'XML';
        aj.resultHandle = null;


        aj.createXMLHttpRequest = function() {
                var request = false;
                if(window.XMLHttpRequest) {
                        request = new XMLHttpRequest();
                        if(request.overrideMimeType) {
                                request.overrideMimeType('text/xml');
                        }
                } else if(window.ActiveXObject) {
                        var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
                        for(var i=0; i<versions.length; i++) {
                                try {
                                        request = new ActiveXObject(versions);
                                        if(request) {
                                                return request;
                                        }
                                } catch(e) {
                                        //alert(e.message);
                                }
                        }
                }
                return request;
        }

        aj.XMLHttpRequest = aj.createXMLHttpRequest();



这一段是想尽一切办法建立一个XMLHttpRequest对象,无论是什么浏览器都能通用了。调用的时候是一个函数Ajax,有两个传入函数recvType和statusId,recvType是ajax返回值的接受类型,有HTML和XML两种类型,Dz一般用的是XML类型;statusID这个是用来指示状态的div。

以下为引用的内容:      

以下为引用的内容:
aj.processHandle = function() {
                if(aj.statusId) {
                        aj.statusId.style.display = '';
                }
                if(aj.XMLHttpRequest.readyState == 1 && aj.statusId) {
                        aj.statusId.innerHTML = xml_http_building_link;
                } else if(aj.XMLHttpRequest.readyState == 2 && aj.statusId) {
                        aj.statusId.innerHTML = xml_http_sending;
                } else if(aj.XMLHttpRequest.readyState == 3 && aj.statusId) {
                        aj.statusId.innerHTML = xml_http_loading;
                } else if(aj.XMLHttpRequest.readyState == 4) {
                        if(aj.XMLHttpRequest.status == 200) {
                                for(k in Ajaxs) {
                                        if(Ajaxs[k] == aj.targetUrl) {
                                                Ajaxs[k] = null;
                                        }
                                }


                                if(aj.statusId) {
                                        aj.statusId.innerHTML = xml_http_data_in_processed;
                                        aj.statusId.style.display = 'none';
                                }
                                if(aj.recvType == 'HTML') {
                                        aj.resultHandle(aj.XMLHttpRequest.responseText, aj);
                                } else if(aj.recvType == 'XML') {
                                        aj.resultHandle(aj.XMLHttpRequest.responseXML.lastChild.firstChild.nodeValue, aj);
                                }
                        } else {
                                if(aj.statusId) {
                                        aj.statusId.innerHTML = xml_http_load_failed;
                                }
                        }
                }
        }



Ajax实例化后的对象aj的processHandle方法,作用当然就是处理ajax请求过程的函数。
具体作用有两点:
第一点,那就是对statusId这个div进行ajax请求过程全程提示,在这段代码的前三分之一的样子就是做这个用的。
注意在register.htm中有对过程的定义,以下的代码引用自./templates/default/register.htm  

以下为引用的内容:
  var profile_seccode_invalid = '{lang register_profile_seccode_invalid}';
                var profile_secanswer_invalid = '{lang register_profile_secqaa_invalid}';
                var profile_username_toolong = '{lang register_profile_username_toolong}';
                var profile_username_tooshort = '{lang register_profile_profile_username_tooshort}';
                var profile_username_illegal = '{lang register_profile_username_illegal}';
                var profile_passwd_illegal = '{lang register_profile_passwd_illegal}';
                var profile_passwd_notmatch = '{lang register_profile_passwd_notmatch}';
                var profile_email_illegal = '{lang register_profile_email_illegal}';
                var profile_email_invalid = '{lang register_profile_email_invalid}';
                var profile_email_censor = '{lang register_profile_email_censor}';
                var profile_email_msn = '{lang register_profile_email_msn}';
                var doublee = parseInt('$doublee');
                var lastseccode = lastsecanswer = lastusername = lastpassword = lastemail = '';
                var xml_http_building_link = '{lang xml_http_building_link}';
                var xml_http_sending = '{lang xml_http_sending}';
                var xml_http_loading = '{lang xml_http_loading}';
                var xml_http_load_failed = '{lang xml_http_load_failed}';
                var xml_http_data_in_processed = '{lang xml_http_data_in_processed}';  


这个便是statusId具体中要提示的文字了,之所以要这样写当然是为了方便多语言。              

第二点是最重要的,当XMLHttpRequest.status=200的时候,那么就表示请求成功并返回了东西,这个时候就用resultHandle这个函数对返回的东西进行处理,可以看到还是分为HTML和XML两种情况分别调用不同的方法,一个是responsText一个是responseXML。      

以下为引用的内容:
aj.get = function(targetUrl, resultHandle) {
                if(in_array(targetUrl, Ajaxs)) {
                        return false;
                } else {
                        arraypush(Ajaxs, targetUrl);
                }
                aj.targetUrl = targetUrl;
                aj.XMLHttpRequest.onreadystatechange = aj.processHandle;
                aj.resultHandle = resultHandle;
                if(window.XMLHttpRequest) {
                        aj.XMLHttpRequest.open('GET', aj.targetUrl);
                        aj.XMLHttpRequest.send(null);
                } else {
                        aj.XMLHttpRequest.open("GET", targetUrl, true);
                        aj.XMLHttpRequest.send();
                }
        }


        aj.post = function(targetUrl, sendString, resultHandle) {
                if(in_array(targetUrl, Ajaxs)) {
                        return false;
                } else {
                        arraypush(Ajaxs, targetUrl);
                }
                aj.targetUrl = targetUrl;
                aj.sendString = sendString;
                aj.XMLHttpRequest.onreadystatechange = aj.processHandle;
                aj.resultHandle = resultHandle;
                aj.XMLHttpRequest.open('POST', targetUrl);
                aj.XMLHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                aj.XMLHttpRequest.send(aj.sendString);
        }
        return aj;
}
10622次点击
2个回复  |  直到 2008-11-7 11:42:59
   
  Reply   
盖茨      2008-11-7 11:42:33
有了这些理论的基础就可以分析一下ajax的具体实现了,下面就以注册过程中的检查用户名在数据库是不是存在并给用户提示这样一个ajax过程进行全程分析。
用到如下的几个文件:

以下为引用的内容:
./register.php
./ajax.php
./include/javascript/common.js
./include/javascript/ajax.js
./template/default/register.htm  


其实register.php这个文件没什么多大的关系,不过register.htm模板是通过它解析过来的,所以就提出来了。

大家都知道在注册过程中是在输完用户名并输入密码的时候才会触发事件检查是不是用户存在,所以很明显,这个是input的onBlur事件。
好了,现在看看./templates/default/register.htm这个文件。

以下为引用的内容:
<tr>
        <td class="altbg1" width="21%"><span class="bold">{lang username}</span></td>
        <td class="altbg2"><div class="input"><input type="text" name="username" size="25" maxlength="15" id="username" onBlur="checkusername()"></div><div id="checkusername"></div>
        </td>
        </tr>  


很简单的HTML代码,注意看到 onBlur="checkusername()"这里,继续往下深入,看看这个函数是做什么的。      

以下为引用的内容:
function checkusername() {
                var username = trim($('username').value);
                if(username == lastusername) {
                        return;
                } else {
                        lastusername = username;
                }
                var cu = $('checkusername');
                var unlen = username.replace(/[^\x00-\xff]/g, "**").length;


                if(unlen < 3 || unlen > 15) {
                        warning(cu, unlen < 3 ? profile_username_tooshort : profile_username_toolong);
                        return;
                }
                ajaxresponse('checkusername', 'action=checkusername&username=' + username);
        }



第一行是得到username的值,也就是我们输入的,lastusername应该是我们在返回的时候不会让用户名消失用的,应该是写入cookie或者是其他。
接下来判断经过了替换的用户名是不是大于15或者小于3,是的话直接调用warning这个函数(稍后讲这样一个函数)并返回,不是的话就调用ajaxresponse函数发出ajax请求,看看ajaxresponse这个函数就是关键所在了。

以下为引用的内容:
        function ajaxresponse(objname, data) {
                var x = new Ajax('XML', objname);
                x.get('ajax.php?inajax=1&' + data, function(s){
                        var obj = $(objname);
                        if(s == 'succeed') {
                                obj.style.display = '';
                                obj.innerHTML = '<img src="{IMGDIR}/check_right.gif" width="13" height="13">';
                                obj.className = "warning";
                        } else {
                                warning(obj, s);
                        }
                });
        }  


ajaxresponse函数来了,这个作用就是实例化一个ajax对象,注意到我们先前说的recvType,就是第一个传入参数,这里固定成了XML,Discuz喜欢用XML(^^),然后发出请求,这里全部用的是get(第二行),地址是ajax.php?inajax=1&加上传入的参数,所以结合上面就变成:ajax.php?inajax=1&action=checkusername&username=用户名,构造出来了一个URL,(大家可以自己测试一下看看返回的是什么东东,通过http://你的URL/ajax.php?inajax=1&action=checkusername&username=用户名)通过XMLHttpRequest发出去,注意那个处理函数:function(s),实际这个函数作为参数已经写出来了,如果最后返回的是succed,那么就在obj这个层里(在这个例子中对应id='checkusername'这个层)显示一个带勾的图,否则的话还是调用warning这个函数。下面就分析这个函数。

以下为引用的内容:

        function warning(obj, msg) {
                if((ton = obj.id.substr(5, obj.id.length)) != 'password2') {
                        $(ton).select();
                }
                obj.style.display = '';
                obj.innerHTML = '<img src="{IMGDIR}/check_error.gif" width="13" height="13">   ' + msg;
                obj.className = "warning";
        }



warning函数前面两次提到,其实这个函数很简单,实现的作用就是在obj这个层里打一个叉,然后写上错误的原因,把obj这个层的CSS class设置成为warning。当然,最开始也验证了一下两次密码是否一致,这里就不说了。

之二

   
  Reply   
盖茨      2008-11-7 11:42:59
接下来当然是要分析这个ajax.php是怎么一回事,它做了哪些使function(s)中能返回我们要的东西。由于只分析检查用户名这一个部分,我这里就只分析action=checkuser这一部分了。

以下为引用的内容:
elseif($action == 'checkusername') {

                $username = trim($username);

                $guestexp = '\xA1\xA1|^Guest|^\xD3\xCE\xBF\xCD|\xB9\x43\xAB\xC8';
                $censorexp = '/^('.str_replace(array('\\*', "\r\n", ' '), array('.*', '|', ''), preg_quote(($censoruser = trim($censoruser)), '/')).')$/i';
                if(preg_match("/^\s*$|^c:\\con\\con$|[%,\*\"\s\t\<\>\&]|$guestexp/is", $username) || ($censoruser && @preg_match($censorexp, $username))) {
                        showmessage('profile_username_illegal');
                }

                $query = $db->query("SELECT uid FROM {$tablepre}members WHERE username='$username'");
                $username = dhtmlspecialchars(stripslashes($username));

                if($db->num_rows($query)) {
                        showmessage('register_check_found');
                }




这里可以看到是标准的php判断了,有点点php基础就能看懂了,基本上的功能就是判断一个用户是不是在后台设置的禁用用户名中。
是的话就showmessage不合法(注:这里的showmessage不是我们理解的那个跳转,而是一个xml文档,为什么会这样我等会会介绍)
然后就从数据库找是不是有这样一个用户,如果是的话就showmessage 发现了已注册的用户名,不是话就都跳过,直接到最后的:

showmessage('succeed');

注意当所有的判断都成功的话就说明合法了,会调用showmessage来显示一个succeed。

最后说一下为什么这里的showmessage不是我们理解的那个跳转了。

注意在register.htm中的ajaxresponse函数有这样一句:x.get('ajax.php?inajax=1&' + data, function(s){
对了,inajax=1,就是这么一个参数,showmessage就天差万别了。

之三

添加一条新回复
您需要登录后才可以回帖 登录 | 成为会员 新浪微博登陆

标签云|手机版|科技先生 ( 京ICP备07036130号 Powered by Discuz! X )

GMT+8, 2024-5-19 09:18