今天由于项目需要要编写一个功能如下的封装Textbox控件的ASP.NET AJAX Client Behavior组件
- 能够限制输入的字符数
- 可以设置是否工作在插入模式(达到最大限制字符数时,如果是插入模式,可以在文本框任意位置继续输入字符,而光标后的字符依次向后移动)
- 兼容IE7 Firefox Safari主流浏览器
考虑到文本框可单行也可多行,将来能要响应一些事件(比如发生字符截断时,触发Truncate事件)。在IE下我订阅了keypress,keyup,paste三个事件,代码如下:
今天由于项目需要要编写一个功能如下的封装Textbox控件的ASP.NET AJAX Client Behavior组件
- 能够限制输入的字符数
- 可以设置是否工作在插入模式(达到最大限制字符数时,如果是插入模式,可以在文本框任意位置继续输入字符,而光标后的字符依次向后移动)
- 兼容IE7 Firefox Safari主流浏览器
考虑到文本框可单行也可多行,将来能要响应一些事件(比如发生字符截断时,触发Truncate事件)。在IE下我订阅了keypress,keyup,paste三个事件,代码如下:
this._onKeypressHnadler = Function.createDelegate(this, this._onKeypress);
this._onTruncateHandler = Function.createDelegate(this, this._onKeyup);
$addHandler(this.get_element(), "paste", this._onPasteHandler);
$addHandler(this.get_element(), "keypress", this._onKeypressHnadler);
$addHandler(this.get_element(), "keyup", this._onTruncateHandler);
这里值得注意的是_onPaste方法。
/// …
var pos = this._get_selectionStart(element);
var handler = Function.createDelegate(this, this._onKeyup);
var callback = Function.createCallback(handler, null);
window.setTimeout(function() {callback(eventObject, pos);}, 0);
},
_onKeyup: function(eventObject, start) {
/// …
},
由于为了保证文本框不能由于粘贴操作导致字符超出限制的字符数,所以在粘贴事件中要对文本框内的字符进行处理,但是在此时文本框的内容还是原来的内容,将要粘贴的内容还没有粘贴到文本框内,所以我需要等粘贴操作完成时再进行处理。
讲到这里才说到主题上,我们先看一下ASP.NET AJAX的两个方法是如何定义的
2 /// <param name="method" type="Function"></param>
3 /// <param name="context" mayBeNull="true"></param>
4 /// <returns type="Function"></returns>
5 var e = Function._validateParams(arguments, [
6 {name: "method", type: Function},
7 {name: "context", mayBeNull: true}
8 ]);
9 if (e) throw e;
10
11
12
13 return function() {
14 var l = arguments.length;
15 if (l > 0) {
16 var args = [];
17 for (var i = 0; i < l; i++) {
18 args[i] = arguments[i];
19 }
20 args[l] = context;
21 return method.apply(this, args);
22 }
23 return method.call(this, context);
24 }
25}
26
27Function.createDelegate = function Function$createDelegate(instance, method) {
28 /// <param name="instance" mayBeNull="true"></param>
29 /// <param name="method" type="Function"></param>
30 /// <returns type="Function"></returns>
31 var e = Function._validateParams(arguments, [
32 {name: "instance", mayBeNull: true},
33 {name: "method", type: Function}
34 ]);
35 if (e) throw e;
36
37
38
39 return function() {
40 return method.apply(instance, arguments);
41 }
42}
43
通过上面的代码我们可以清楚地看到createDelegate是给指定的函数传递this指针,createCallback是给指定的函数传递一个参数context。但是回头看看我们_onKeyup函数需要两个参数,如何才能将两个参数传递过来呢?
var handler = Function.createDelegate(this, this._onKeyup); // 传递当前this指针给函数_onKeyup
var callback = Function.createCallback(handler, null); // 创建callback
window.setTimeout(function() {callback(eventObject, pos);}, 0); // 调用callback(eventObject, pos) 传递两个参数到_onKeyup函数中
总结:
使用Function.createCallback如果想传递一个参数给回调函数,只需要Function.createCallback(instance, context)就行了。
如果想传递多个参数给回调函数,需要先创建一个callback,然后自己调用将参数传递过去。这里有一个小技巧,比如要传递三个参数(args1, args2, args3)过去可以如下写:
callback(args1, args2);
但是个人不推荐使用上面的写法,毕竟可读性不是很好。
其实还是使用原生态的最简单
return function() {method.apply(instance, args);}
}
上面就可以使用foo(this, this._onKeyup, [args1, args2, args3])来传递参数了。