Skip navigation.

极湖

无不用其“极”

Posts tagged with "JavaScript"

ExtJS 2.x 的多行工具条实现

,

通常的写法
tbar: [{
    ... ...
}, {
    ... ...
}]

这样实现的工具条只有一行。

有时候工具条按钮比较多,一行放不下,需要加行。
简单的做法是:
tbar: new Ext.Panel({
    border: false,
    items:[{
        xtype: 'toolbar',
        items: [
            ... ...
        ]
    }, {
        xtype: 'toolbar',
        items: [
            ... ...
        ]
    }, {
        xtype: 'toolbar',
        items: [
            ... ...
        ]
    }]
})

三个 JavaScript 工具 + 批处理

,

收集了三个针对 JavaScript 的工具:

1. JavaScript Lint
用于 js 查错。

2. YUI Compressor
用于压缩 js 文件。

3. Closure Compiler
用于压缩和优化 js 文件。

我把以上三个工具都放在 C:\jsl 下面,并把该目录加入系统变量 PATH。
随后在 C:\jsl 下新作三个 bat 文件,分别如下:

jsl.bat
@echo off
c:\jsl\jsl.exe -conf c:\jsl\jsl.default.conf -process "%1"


yuic.bat
@echo off
java -jar C:\jsl\yuicompressor-2.4.2.jar  -v --charset utf-8 -o "%2" "%1"


jsc.bat
@echo off
java -jar c:\jsl\compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js "%1" > "%2"


使用例:

> jsl test.js
> yuic test.js test.min.js
> jsc test.js test.compiled.js

给 ExtJS 的输入控件增加提示功能

,

在页面的 js 代码最上层,追加以下代码
Ext.override(Ext.form.Field, {
    afterRender: function() {
        this.initEvents();
        this.initValue();
        //取得控件的标签
        var findLabel = function(field) {
            var wrapDiv = null;
            var label = null
            wrapDiv = field.getEl().up('div.x-form-element');
            if(wrapDiv) {
                label = wrapDiv.child('label');        
                if(label) {
                    return label;
                }
            }
            wrapDiv = field.getEl().up('div.x-form-item');
            if(wrapDiv) {
                label = wrapDiv.child('label');        
            }
            return label;
        }
        //给控件追加 QuickTips
        if(this.qtip) {
            Ext.QuickTips.register({
                target: this.getEl(),
                title: '',
                text: this.qtip,
                enabled: true
            });
            var label = findLabel(this);
            if(label) {
                Ext.QuickTips.register({
                    target: label,
                    title: '',
                    text: this.qtip,
                    enabled: true
                });
            }
        }
        Ext.form.Field.superclass.afterRender.call(this);
    }
});

之后,在生成输入控件的代码中,若有以下属性
qtip: '提示消息'

当鼠标移动到控件上面,提示文字就会显示。

参考: http://www.yui-ext.com/forum/showthread.php?t=11537

JavaScript: 判断字符串是否数字

一个小小的数字判断功能,也有很多学问。
请看解答: http://stackoverflow.com/questions/18082/validate-numbers-in-javascript-isnumeric

总结一下文章中提到的方法:

1. 内建函数 isNaN
这个不用多说。

2. 正则表达式
function isNumeric(x) {
   return /^-?\d*\.?\d+$/.test(x);
}


3. 利用类型变换
function isNumeric(x) {
    return parseFloat(x) == x;
}


4. 利用“潜规则”
function isNumeric(x) {
   return (x - 0) == x && x.length > 0;
}


Stackoverflow 上投票最多的竟然是利用“潜规则”的方法。看来,只有掌握了“潜规则”,才算真正精通一门语言。

用 JavaScript 实现的 md5 算法

, ,

这儿找到的代码,稍做修改(只是修改语法,尽量使其简洁)之后如下:
function md5(sText) {
  var MD5_T = [
    0x00000000, 0xd76aa478, 0xe8c7b756, 0x242070db,
    0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613,
    0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1,
    0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e,
    0x49b40821, 0xf61e2562, 0xc040b340, 0x265e5a51,
    0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681,
    0xe7d3fbc8, 0x21e1cde6, 0xc33707d6, 0xf4d50d87,
    0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9,
    0x8d2a4c8a, 0xfffa3942, 0x8771f681, 0x6d9d6122,
    0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60,
    0xbebfbc70, 0x289b7ec6, 0xeaa127fa, 0xd4ef3085,
    0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8,
    0xc4ac5665, 0xf4292244, 0x432aff97, 0xab9423a7,
    0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d,
    0x85845dd1, 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314,
    0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb,
    0xeb86d391
  ];

  var MD5_round1 = [
    [ 0, 7, 1], [ 1,12, 2],
    [ 2,17, 3], [ 3,22, 4],
    [ 4, 7, 5], [ 5,12, 6],
    [ 6,17, 7], [ 7,22, 8],
    [ 8, 7, 9], [ 9,12,10],
    [10,17,11], [11,22,12],
    [12, 7,13], [13,12,14],
    [14,17,15], [15,22,16]
  ];

  var MD5_round2 = [
    [ 1, 5,17], [ 6, 9,18],
    [11,14,19], [ 0,20,20],
    [ 5, 5,21], [10, 9,22],
    [15,14,23], [ 4,20,24],
    [ 9, 5,25], [14, 9,26],
    [ 3,14,27], [ 8,20,28],
    [13, 5,29], [ 2, 9,30],
    [ 7,14,31], [12,20,32]
  ];

  var MD5_round3 = [
    [ 5, 4,33], [ 8,11,34],
    [11,16,35], [14,23,36],
    [ 1, 4,37], [ 4,11,38],
    [ 7,16,39], [10,23,40],
    [13, 4,41], [ 0,11,42],
    [ 3,16,43], [ 6,23,44],
    [ 9, 4,45], [12,11,46],
    [15,16,47], [ 2,23,48]
  ];

  var MD5_round4 = [
    [ 0, 6,49], [ 7,10,50],
    [14,15,51], [ 5,21,52],
    [12, 6,53], [ 3,10,54],
    [10,15,55], [ 1,21,56],
    [ 8, 6,57], [15,10,58],
    [ 6,15,59], [13,21,60],
    [ 4, 6,61], [11,10,62],
    [ 2,15,63], [ 9,21,64]
  ];

  function MD5_F(x, y, z) { return (x & y) | (~x & z); }
  function MD5_G(x, y, z) { return (x & z) | (y & ~z); }
  function MD5_H(x, y, z) { return x ^ y ^ z; }
  function MD5_I(x, y, z) { return y ^ (x | ~z); }

  var MD5_round = [
    [MD5_F, MD5_round1],
    [MD5_G, MD5_round2],
    [MD5_H, MD5_round3],
    [MD5_I, MD5_round4]
  ];

  function MD5_pack(n32) {
    return String.fromCharCode(n32 & 0xff)
      + String.fromCharCode((n32 >>> 8) & 0xff)
      + String.fromCharCode((n32 >>> 16) & 0xff)
      + String.fromCharCode((n32 >>> 24) & 0xff);
  }

  function MD5_unpack(s4) {
    return  s4.charCodeAt(0)
      | (s4.charCodeAt(1) <<  8)
      | (s4.charCodeAt(2) << 16)
      | (s4.charCodeAt(3) << 24);
  }

  function MD5_number(n) {
    while (n < 0)
      n += 4294967296;
    while (n > 4294967295)
      n -= 4294967296;
    return n;
  }

  function MD5_apply_round(x, s, f, abcd, r) {
    var a, b, c, d;
    var kk, ss, ii;
    var t, u;

    a = abcd[0];
    b = abcd[1];
    c = abcd[2];
    d = abcd[3];
    kk = r[0];
    ss = r[1];
    ii = r[2];

    u = f(s[b], s[c], s[d]);
    t = s[a] + u + x[kk] + MD5_T[ii];
    t = MD5_number(t);
    t = ((t<<ss) | (t>>>(32-ss)));
    t += s[b];
    s[a] = MD5_number(t);
  }

  function MD5_hash(data) {
    var abcd, x, state, s;
    var len, index, padLen, f, r;
    var i, j, k;
    var tmp;

    state = [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476];
    len = data.length;
    index = len & 0x3f;
    padLen = (index < 56) ? (56 - index) : (120 - index);
    if(padLen > 0) {
      data += '\x80';
      for(i = 0; i < padLen - 1; i++)
        data += '\x00';
    }
    data += MD5_pack(len * 8);
    data += MD5_pack(0);
    len += padLen + 8;
    abcd = [0, 1, 2, 3];
    x = [16];
    s = [4];

    for(k = 0; k < len; k += 64) {
      for(i = 0, j = k; i < 16; i++, j += 4) {
        x[i] = data.charCodeAt(j)
          | (data.charCodeAt(j + 1) <<  8)
          | (data.charCodeAt(j + 2) << 16)
          | (data.charCodeAt(j + 3) << 24);
      }
      for(i = 0; i < 4; i++)
        s[i] = state[i];
      for(i = 0; i < 4; i++) {
        f = MD5_round[i][0];
        r = MD5_round[i][1];
        for(j = 0; j < 16; j++) {
          MD5_apply_round(x, s, f, abcd, r[j]);
          tmp = abcd[0];
          abcd[0] = abcd[3];
          abcd[3] = abcd[2];
          abcd[2] = abcd[1];
          abcd[1] = tmp;
        }
      }

      for(i = 0; i < 4; i++) {
        state[i] += s[i];
        state[i] = MD5_number(state[i]);
      }
    }

    return MD5_pack(state[0])
      + MD5_pack(state[1])
      + MD5_pack(state[2])
      + MD5_pack(state[3]);
  }

  var i, out, c;
  var bit128;

  bit128 = MD5_hash(sText);
  out = '';
  for(i = 0; i < 16; i++) {
    c = bit128.charCodeAt(i);
    out += '0123456789abcdef'.charAt((c>>4) & 0xf);
    out += '0123456789abcdef'.charAt(c & 0xf);
  }
  return out;
}

各大 Javascript 框架DOM选择器速度比拼

,

看了一下 SlickSpeed,各大 JS 框架都已更新至今天最新发布版。

在自己的机器上用 Firefox 3.0.11 测试了一下,结果如图:


从这个结果来看,DOMAssistant 2.8 最强(65 ms),ExtJS Core 3.0 次之(260 ms),最差是 YUI 2.7.0(811 ms),最强和最差之间相差10倍还多!

DOMAssistant 我还没用过,看来得关注一下了。

ExtJS: 深度查找树节点

, ,

方法一: 自己做递归函数
function findChildRecursively(rootNode, key, value) {
    var nodes = rootNode.childNodes;
    for(var i = 0; i < nodes.length; i++) {
        if(nodes[i].attributes[key] == value){
            return nodes[i];
        } else {
            if(!nodes[i].isLeaf()) {
                // 查找结果不包含 Folder 的情况下
                continue;
            }
            if(!nodes[i].isLoaded()) {
                //加载子节点,AsyncTreeNode 需要,TreeNode 则不需
                nodes[i].reload();
            }
            if(node = findChildRecursively(nodes[i], key, value)) {
                return node;
            }
        }
    }
    return null;
} 

方法二: 利用现成方法 cascade
var node = null;
rootNode.cascade(function(n) {
    if(n.isLeaf() && !n.isLoaded()) {
        n.reload();
        return true;
    }
    if(n.attributes[key] == value) {
        node = n;
        return false;
    }
    return true;
});

JavaScript: 取得字符串的字节数

, ,

代码:
//四舍五入
function _round(num, X) {
    X = X || 2;
    return Math.round(num*Math.pow(10, X))/Math.pow(10, X);
}

//取得字符串的字节数
function _byteLength(str){
    //方法一:正则
    if(!str) return 0;
    return str.replace(/[^\x00-\xFF]/g,'**').length;
    //方法二:循环
    /*
    var byteLen=0,len=str.length;
    for(var i=0; i<len; i++){
        if(str.charCodeAt(i)>255){
            byteLen += 2;
        } else {
            byteLen++;
        }
    }
    return byteLen;
    */
}

//测试
var str = "試験helloテストテスト";
var size = _byteLength(str);
alert(size + ' bytes');
alert(_round(size/1024) + ' Kb');

console.log Everywhere

, , ,

console.log 原先是 Firefox 的“专利”,严格说是安装了 Firebugs 之后的 Firefox 所独有的调试“绝招”。

这一招,IE8 学会了,不过用起来比 Firebugs 麻烦,只有在开启调试窗口(F12)的时候,console.log 才能出结果,不然就报错。

今天看到 Opera 也有个叫 dragonfly 的东东,用这东西查看 DOM,已经可以和 Firebug 媲美,然而还是不能用 console.log。于是有人就提供了这样两句代码:

window.console = window.console || {};
console.log || (console.log = opera.postError);


经测试,以上代码好使。

至此,Firefox/IE/Opera 都能用上 console.log 了。

当然,IE 和 Opera 下的 console.log 比起 Firebugs 原创的 console.log,还是太过简单,比如参数是 Object 或者数组就没有进一步的显示功能。

IME 打开时 Firefox 不触发 keyup 之解决方法

, ,

输入法打开时, Firefox 不触发 keyup 事件。经常写javascript代码的人,尤其是中日韩等国的人,都可能会遇上这个不大好解决的问题,。

在一个日文 Blog 上找到了解决办法,用 jQuery 通过 text 事件实现。
自己写了一段测试代码如下:

var logFunc = function(e){
  console.log($(this).val());
  if(e){
    // keyup 时能取到键值
    console.log(e.keyCode)
  }
};
$(':text').keyup(logFunc).text('text', logFunc);
November 2009
S M T W T F S
October 2009December 2009
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30