« 2010年8月的文章归档

正则里 ‘ ?’ 的艺术

? 0或1个
?: 子表达式不记录
?= 后面必需跟着XXX
?! 后面不能跟着XXX
*? +? 非贪婪匹配

新浪微博的字数改变及字符计算

今天有个哥们让我看一下新浪微博的字数改变的实现及字符数计算的算法。

现把它关键部份抽出如下。

var testlimit = function(func) {
    var len = getLength(elements.editor.value);
    if (typeof func === "function") {
        func(len)
    }
    if (len > 0 && len <= 140) {
        return true
    } else {
        return false
    }
};
var doLimit = function(event) {
    if (!allow) {
        return
    }
    if (event && event.ctrlKey == true && (event.keyCode == "13" || event.keyCode == "10")) {
        return
    }
    if (testlimit(config.onLimit)) {
        submitEnable();
        casheInput.save()
    } else {
        submitDisable()
    }
};
onLimit: function(len) {
    if (len >= 0 && len <= 140) {
        $E("publisher_info").className = "wordNumBg";
        $E("publisher_info").innerHTML = $CLTMSG.CD0071.replace(/#\{cls\}/, "pipsLim").replace(/#\{len\}/, 140 - len)
    } else {
        $E("publisher_info").className = "wordNumBg error";
        var _src = 'src="' + scope.$BASECSS + scope.$PRODUCT_NAME + 'style/images/common/transparent.gif" ';
        var _num = $CLTMSG.CD0072.replace(/#\{len\}/, (140 - len) * ( - 1));
        $E("publisher_info").innerHTML = '
' + _num + '
' } }
//阿飞:对URL的判断
var regexp = new RegExp("(http://)+(([-A-Za-z0-9]+(.[-A-Za-z0-9]+)*(.[-A-Za-z]{2,5}))|([0-9]{1,3}(.[0-9]{1,3}){3}))(:[0-9]*)?(/[-A-Za-z0-9_$.+!*(),;:@&=?/~#%]*)*", "gi");
var getLength = function(str) {
    var reg = new RegExp(config.emptyStr[0], "g");
    var len = Core.String.trim(str.replace(reg, "")).length;
    if (len > 0) {
        var min = 41,
        max = 140,
        tmp = str;
        var urls = str.match(regexp) || [];
        var urlCount = 0;
        for (var i = 0,
        len = urls.length; i < len; i++) {
            var count = Core.String.byteLength(urls[i]);
            if (count > min) {
                urlCount += count <= max ? 21 : (21 + (count - max) / 2);
                tmp = tmp.replace(urls[i], "")
            }
        }
        return Math.ceil(urlCount + Core.String.byteLength(tmp) / 2)
    } else {
        return 0
    }
};
Core.Events.addEvent = function(elm, func, evType, useCapture) {
    var _el = $E(elm);
    if (_el == null) {
        trace("addEvent 找不到对象:" + elm);
        return
    }
    if (typeof useCapture == "undefined") {
        useCapture = false
    }
    if (typeof evType == "undefined") {
        evType = "click"
    }
    if (_el.addEventListener) {
        _el.addEventListener(evType, func, useCapture);
        return true
    } else {
        if (_el.attachEvent) {
            var r = _el.attachEvent("on" + evType, func);
            return true
        } else {
            _el["on" + evType] = func
        }
    }
};
Core.Events.addEvent(elements.editor, doLimit, "keyup");
Core.Events.addEvent(elements.editor, doLimit, "input");
Core.String.byteLength = function(str) {
    if (typeof str == "undefined") {
        return 0
    }
    var aMatch = str.match(/[^\x00-\x80]/g);
    return (str.length + (!aMatch ? 0 : aMatch.length))
};

新浪微博的textarea框侦听了两个事件,一个是keyup,一个是input。input只在非IE浏览器支持,他们合伙欺负IE,不过IE里有一个类似的事件叫onpropertychange,只要textarea/input里发生变化就触发,有点像select的change事件,主要是针对用户用鼠标复制再用鼠标粘贴时特有用。

还有一个就是计算字节数,这个看官自行领悟吧,2个半角、字母、数字算一个字,1个全角、汉字算一个字。

PHP中UT8编码下对应的字节计算方法

//第一种
ceil(((strlen($str) + mb_strlen($str,'utf-8')) / 4));
//第二种
$doubleByteregex = '/[^\x{00}-\x{80}]/u';
preg_match_all($doubleByteregex, $str, $doubleByteArray);
ceil((mb_strlen($str,'utf-8') + count($doubleByteArray[0]))/2) ;