15 May 2005
This post may be outdated due to it was written on 2005. The links may be broken. The code may be not working anymore. Leave comments if needed.

今天闲着无事就想着用 Ajax 实现论坛的用户名检测。

先简化了下 Ajax.js, 让它能在不同的程序里指定不同的 url, param 和 div 的 id.


var req, Div;
var debug = 0;

function Ajax(DivName, url, parameters) {
    if (window.XMLHttpRequest) req = new XMLHttpRequest();
    else if (window.ActiveXObject) req = new ActiveXObject("Microsoft.XMLHTTP");
    else return; // fall on our sword
    req.onreadystatechange = processReqChange;
    req.open("POST", url, true);
    req.setRequestHeader('Connection', 'close');
    req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    req.send(parameters);
    Div = document.getElementById(DivName);
}

function processReqChange() {
    // only if req shows "complete"
    if (req.readyState == 4) {
        // only if "OK"
        if (req.status == 200) {
            // show content in div
            Div.innerHTML = req.responseText;
        } else {
            if (debug) alert('status is not 200,but ' + req.status);
        }
    }
}
调用的代码为:
<input type="text" maxlength="12" name="username" onblur="CheckName(this.value)"> * 2 - 12 字符(1 - 6 汉字)
<script language="javascript" type="text/javascript" src="./js/Ajax.js"></script>
<script language="javascript" type="text/javascript">
    function CheckName(aObj) {
        try { Ajax('CheckName', 'CheckName.pl', 'mode=Ajax&name=' + encodeURIComponent(aObj)); }
        catch (e) { return; }
    }
</script>
<div id="CheckName"></div>
Update: 感谢 easunlee 的提醒, encodeURIComponent 对 IE5.5 以下无效,所以我们用了 try+catch 在无效情况下不调用该函数(和|或者)弹出 alert 提示升级浏览器。

问题出现了

首先解释下 encodeURIComponent 的作用:将文本字符串编码为一个有效的统一资源标识符 (URI)。
为什么要用这个是因为我想把 username 整个当做参数传递给 CGI, 而不让 CGI 将 username 分割掉。这话听不明白的话我换种方式来说,如果 username = 'a&foo=boo' 而不用 encodeURIComponent 的话,整个参数就成了 name=a&foo=boo, 这样 CGI 就获得两个参数 name 和 foo. 这不是我们想要的。
Javascript 里还有个同样功能的函数 encodeURI, 但是此方法不会对下列字符进行编码:":"、"/"、";" 和 "?"。

刚开始我都输入英文检测代码是否运行正常,后来因为我不想用户名为“客人”,所以就试了下。
结果很令我奇怪,div 为 CheckName 里的输出是“瀹汉”。
一看到这个,第一反应就是编码问题。

客人经过 JS 的 encodeURIComponent 转化后得到的值为 %E5%AE%A2%E4%BA%BA, 而我直接在浏览器里输出客人后转的值为 %BF%CD%C8%CB. 辨别后,猜测 Javascript encodeURIComponent 将“客人”转为了 utf-8 编码。

于是在 CheckName.pl 里加了编码转换。

use Encode qw/from_to/;
my $name = $q->param('name');
from_to($name, "utf8", "gb2312");
终于搞定。

The last words

希望对碰到同样问题的各位能有所帮助。 Have fun!


blog comments powered by Disqus