本帖最后由 beijing200808 于 2011-4-1 14:48 编辑
简单分析一下 Discuz! X1.5 注册页面的 js 验证过程
首先,看一下模板文件,template\default\member\register.htm,找到如下代码 - <label><em>{lang username}:</em><input type="text" id="username" name="{$_G['setting']['reginput']['username']}" autocomplete="off" size="25" maxlength="15" value="" onBlur="checkusername()" tabindex="1" class="txt" /> *</label>
复制代码在 username 的标签里,有个onBlur事件,当username文本框失去焦点的时候,会触发onBlur事件,执行checkusername函数。继续跟踪 checkusername函数 - function checkusername() {
- var username = trim($('username').value);
- if(username == '' || username == lastusername) {
- return;
- } else {
- lastusername = username;
- }
- var unlen = username.replace(/[^\x00-\xff]/g, "**").length;
- if(unlen < 3 || unlen > 15) {
- errorhandle_register(unlen < 3 ? profile_username_tooshort : profile_username_toolong, {'key':1});
- return;
- }
- ajaxget('forum.php?mod=ajax&infloat=register&handlekey=register&action=checkusername&username=' + (BROWSER.ie && document.charset == 'utf-8' ? encodeURIComponent(username) : username), 'returnmessage4');
- }
复制代码当输入的用户名长度小于3或者大于15时,会通过errorhandle_register函数提示用户名长度过短或者太长。如果用户名长度合理,然后通过ajaxget函数去异步验证用户名的合法性及唯一性。继续跟踪ajaxget函数(在 static\js\common.js 文件中) - function ajaxget(url, showid, waitid, loading, display, recall) {
- waitid = typeof waitid == 'undefined' || waitid === null ? showid : waitid;
- var x = new Ajax();
- x.setLoading(loading);
- x.setWaitId(waitid);
- x.display = typeof display == 'undefined' || display == null ? '' : display;
- x.showId = $(showid);
- if(x.showId) x.showId.orgdisplay = typeof x.showId.orgdisplay === 'undefined' ? x.showId.style.display : x.showId.orgdisplay;
- if(url.substr(strlen(url) - 1) == '#') {
- url = url.substr(0, strlen(url) - 1);
- x.autogoto = 1;
- }
- var url = url + '&inajax=1&ajaxtarget=' + showid;
- x.get(url, function(s, x) {
- var evaled = false;
- if(s.indexOf('ajaxerror') != -1) {
- evalscript(s);
- evaled = true;
- }
- if(!evaled && (typeof ajaxerror == 'undefined' || !ajaxerror)) {
- if(x.showId) {
- x.showId.style.display = x.showId.orgdisplay;
- x.showId.style.display = x.display;
- x.showId.orgdisplay = x.showId.style.display;
- ajaxinnerhtml(x.showId, s);
- ajaxupdateevents(x.showId);
- if(x.autogoto) scroll(0, x.showId.offsetTop);
- }
- }
- ajaxerror = null;
- if(typeof recall == 'function') {
- recall();
- } else {
- eval(recall);
- }
- if(!evaled) evalscript(s);
- });
- }
复制代码在这个函数里,主要的处理过程是通过 x 对象的 get 属性,在 Ajax 这个function 中,创建了 Ajax 对象 aj,然后指定get的处理方法,通过这种方式,去获取给定URL('forum.php?mod=ajax&infloat=register&handlekey=register&action=checkusername&username=' + (BROWSER.ie && document.charset == 'utf-8' ? encodeURIComponent(username) : username))的处理结果。 如果用户输入的信息有问题,ajaxget函数获取返回的结果,将其显示在returnmessage4这个标签里。例如 这是针对用户名的处理过程,邮箱的验证过程也是这样。
如果用户输入的信息在提交表单时,页面没有任何提示,当用户点击“注册”按钮时,由于form指定了onsubmit属性,所以页面并没有直接提交。 - <form method="post" autocomplete="off" name="register" id="registerform" enctype="multipart/form-data" onsubmit="ajaxpost('registerform', 'returnmessage4', 'returnmessage4', 'onerror');return false;" action="member.php?mod={$_G[setting][regname]}">
复制代码在onsubmit中,return false停止form的默认操作,执行ajaxpost函数,继续跟踪ajaxpost函数 - function ajaxpost(formid, showid, waitid, showidclass, submitbtn, recall) {
- var waitid = typeof waitid == 'undefined' || waitid === null ? showid : (waitid !== '' ? waitid : '');
- var showidclass = !showidclass ? '' : showidclass;
- var ajaxframeid = 'ajaxframe';
- var ajaxframe = $(ajaxframeid);
- var formtarget = $(formid).target;
- var handleResult = function() {
- var s = '';
- var evaled = false;
- showloading('none');
- try {
- if(BROWSER.ie) {
- s = $(ajaxframeid).contentWindow.document.XMLDocument.text;
- } else {
- if(BROWSER.safari > 0) {
- s = $(ajaxframeid).contentWindow.document.documentElement.firstChild.wholeText;
- } else {
- s = $(ajaxframeid).contentWindow.document.documentElement.firstChild.nodeValue;
- }
- }
- } catch(e) {
- s = '内部错误,无法显示此内容';
- }
- if(s != '' && s.indexOf('ajaxerror') != -1) {
- evalscript(s);
- evaled = true;
- }
- if(showidclass) {
- $(showid).className = showidclass;
- }
- if(submitbtn) {
- submitbtn.disabled = false;
- }
- if(!evaled && (typeof ajaxerror == 'undefined' || !ajaxerror)) {
- ajaxinnerhtml($(showid), s);
- }
- ajaxerror = null;
- if($(formid)) $(formid).target = formtarget;
- if(typeof recall == 'function') {
- recall();
- } else {
- eval(recall);
- }
- if(!evaled) evalscript(s);
- ajaxframe.loading = 0;
- $('append_parent').removeChild(ajaxframe.parentNode);
- };
- if(!ajaxframe) {
- var div = document.createElement('div');
- div.style.display = 'none';
- div.innerHTML = '<iframe name="' + ajaxframeid + '" id="' + ajaxframeid + '" loading="1"></iframe>';
- $('append_parent').appendChild(div);
- ajaxframe = $(ajaxframeid);
- } else if(ajaxframe.loading) {
- return false;
- }
- _attachEvent(ajaxframe, 'load', handleResult);
- showloading();
- $(formid).target = ajaxframeid;
- var action = $(formid).getAttribute('action');
- action = hostconvert(action);
- $(formid).action = action.replace(/\&inajax\=1/g, '')+'&inajax=1';
- $(formid).submit();
- if(submitbtn) {
- submitbtn.disabled = true;
- }
- doane();
- return false;
- }
复制代码在这个函数中,先想表单中动态添加了一个iframe,然后给handleresult指定了处理方法,将表单的提交目标改成了刚刚创建的iframe,重新调整了form的action ,然后执行表单的submit操作,执行完后,在iframe加载内容的同时,通过handleresult获取了iframe内容,并将返回的结果显示在returnmessage4这个标签里。例如 上面的处理过程,实际是利用 js 提交数据和处理返回结果的显示。真正的数据逻辑处理部分,还是在URL对应的PHP文件中。在这些文件中,如果执行异常,多是通过showmessage函数来返回给 js 异常信息。在showmessage函数中,又是通过
inajax、msgtype这两个参数来具体控制返回信息的格式,其中,inajax参数已经在 js 提交数据前已经指定。 |