浏览 2840 次
锁定老帖子 主题:Ext.js(v2.1)源码分析
精华帖 (0) :: 良好帖 (0) :: 新手帖 (6) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-08-04
* 1.Ext类是整个Ext体系的基础和核心,包含核心代码和函数。 * Ext类是单例的,不能直接创建。 */ /** * 2.复制c中所有属性到o中,如果有defaults,属性也会复制到o中。 * 如果defaults中的属性和c中相同,最后相同属性值是c中的。 * 这里复制采用的是关联数组的形式。 * @param {} o 目标对象 * @param {} c 源对象 * @param {} defaults 默认值对象 * @return {} 返回目标对象 */ Ext.apply = function(o, c, defaults){ if(defaults){ // no "this" reference for friendly out of scope calls Ext.apply(o, defaults); } if(o && c && typeof c == 'object'){ for(var p in c){ o[p] = c[p]; } } return o; }; /** * 3.添加Function类原型的方法,也即添加属性给Function的原型。 * 这里一共两个参数,第一个是Function类的原型,第二个是直接量创建的对象。 * 第二个对象中有5个属性,每个属性都是一个方法。也即执行完后,每个函数的原型中都添加了这5个方法,可以随时调用。 * * 第一个方法是createCallback,可以接受参数数组,表示window方位内的方法需要被回调,也即类方法被回调;因为类方法就是window对象的方法。 * * 第二个方法是createDelegate,第一个参数是特定对象,表示特定对象的方法需要被回调,也即实例方法被回调,方法里面一定有具体的this引用,因为实例方法一般需要this引用。 * 当特定对象没有被指定时,就是window对象,这时等同于createCallback方法。 * * 第三个方法是defer,第一个参数是延迟时间(单位毫秒),其余类似于createDelegate方法。内部使用setTimeout函数。 * * 第四个方法是createSequence,接受两个参数,第一个是函数,第二个表示第一个参数的范围。两个函数使用相同的参数,调用函数先执行,然后执行形参函数,返回调用函数。 * * 第五个方法是createInterceptor,形式参数与createSequence一样,但是形参函数先于调用函数执行。两个函数接受相同的参数,如果形参函数返回true,调用函数执行;否则,调用函数不执行。最终结果是调用函数的执行结果。 * 这个方法可以称作"前拦截",createSequence可以称作"后拦截"。 */ Ext.apply(Function.prototype, { /** * Creates a callback that passes arguments[0], arguments[1], arguments[2], ... * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code> * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always * executes in the window scope. * <p>This method is required when you want to pass arguments to a callback function. If no arguments * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn). * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function * would simply execute immediately when the code is parsed. Example usage: * <pre><code> var sayHi = function(name){ alert('Hi, ' + name); } // clicking the button alerts "Hi, Fred" new Ext.Button({ text: 'Say Hi', renderTo: Ext.getBody(), handler: sayHi.createCallback('Fred') }); </code></pre> * @return {Function} The new function */ createCallback : function(/*args...*/){ // make args available, in function below var args = arguments; var method = this; return function() { return method.apply(window, args); }; }, /** * Creates a delegate (callback) that sets the scope to obj. * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code> * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the * callback points to obj. Example usage: * <pre><code> var sayHi = function(name){ // Note this use of "this.text" here. This function expects to // execute within a scope that contains a text property. In this // example, the "this" variable is pointing to the btn object that // was passed in createDelegate below. alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.'); } var btn = new Ext.Button({ text: 'Say Hi', renderTo: Ext.getBody() }); // This callback will execute in the scope of the // button instance. Clicking the button alerts // "Hi, Fred. You clicked the "Say Hi" button." btn.on('click', sayHi.createDelegate(btn, ['Fred'])); </code></pre> * @param {Object} obj (optional) The object for which the scope is set * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller) * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding, * if a number the args are inserted at the specified position * @return {Function} The new function */ createDelegate : function(obj, args, appendArgs){ var method = this; return function() { var callArgs = args || arguments; if(appendArgs === true){ callArgs = Array.prototype.slice.call(arguments, 0); callArgs = callArgs.concat(args); }else if(typeof appendArgs == "number"){ callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first var applyArgs = [appendArgs, 0].concat(args); // create method call params Array.prototype.splice.apply(callArgs, applyArgs); // splice them in } return method.apply(obj || window, callArgs); }; }, /** * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage: * <pre><code> var sayHi = function(name){ alert('Hi, ' + name); } // executes immediately: sayHi('Fred'); // executes after 2 seconds: sayHi.defer(2000, this, ['Fred']); // this syntax is sometimes useful for deferring // execution of an anonymous function: (function(){ alert('Anonymous'); }).defer(100); </code></pre> * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately) * @param {Object} obj (optional) The object for which the scope is set * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller) * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding, * if a number the args are inserted at the specified position * @return {Number} The timeout id that can be used with clearTimeout */ defer : function(millis, obj, args, appendArgs){ var fn = this.createDelegate(obj, args, appendArgs); if(millis){ return setTimeout(fn, millis); } fn(); return 0; }, /** * Create a combined function call sequence of the original function + the passed function. * The resulting function returns the results of the original function. * The passed fcn is called with the parameters of the original function. Example usage: * <pre><code> var sayHi = function(name){ alert('Hi, ' + name); } sayHi('Fred'); // alerts "Hi, Fred" var sayGoodbye = sayHi.createSequence(function(name){ alert('Bye, ' + name); }); sayGoodbye('Fred'); // both alerts show </code></pre> * @param {Function} fcn The function to sequence * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window) * @return {Function} The new function */ createSequence : function(fcn, scope){ if(typeof fcn != "function"){ return this; } var method = this; return function() { var retval = method.apply(this || window, arguments); fcn.apply(scope || this || window, arguments); return retval; }; }, /** * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, * the original one is not called. The resulting function returns the results of the original function. * The passed fcn is called with the parameters of the original function. Example usage: * <pre><code> var sayHi = function(name){ alert('Hi, ' + name); } sayHi('Fred'); // alerts "Hi, Fred" // create a new function that validates input without // directly modifying the original function: var sayHiToFriend = sayHi.createInterceptor(function(name){ return name == 'Brian'; }); sayHiToFriend('Fred'); // no alert sayHiToFriend('Brian'); // alerts "Hi, Brian" </code></pre> * @param {Function} fcn The function to call before the original * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window) * @return {Function} The new function */ createInterceptor : function(fcn, scope){ if(typeof fcn != "function"){ return this; } var method = this; return function() { fcn.target = this; fcn.method = method; if(fcn.apply(scope || this || window, arguments) === false){ return; } return method.apply(this || window, arguments); }; } }); /** * 3.添加String类原型的方法,第一个参数是String类,可以添加的方法有3个。 * * 第一个方法是escape,忽略某个字符串中的'和\,只有一个参数,表示特定字符串。 * * 第二个方法是leftPad,表示左填充,第一个参数表示字符串,第二个参数表示最终的长度,第三个参数表示填充符号。 * * 第三个方法是特定位置填充,特定位置使用{0}、{1}这样的表示方法,每个位置填充指定的字符串。第一个参数是格式化样式,后面的参数是需要被填充的字符串 */ Ext.applyIf(String, { /** * Escapes the passed string for ' and \ * @param {String} string The string to escape * @return {String} The escaped string * @static */ escape : function(string) { return string.replace(/('|\\)/g, "\\$1"); }, /** * Pads the left side of a string with a specified character. This is especially useful * for normalizing number and date strings. Example usage: * <pre><code> var s = String.leftPad('123', 5, '0'); // s now contains the string: '00123' </code></pre> * @param {String} string The original string * @param {Number} size The total length of the output string * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ") * @return {String} The padded string * @static */ leftPad : function (val, size, ch) { var result = new String(val); if(!ch) { ch = " "; } while (result.length < size) { result = ch + result; } return result.toString(); }, /** * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each * token must be unique, and must increment in the format {0}, {1}, etc. Example usage: * <pre><code> var cls = 'my-class', text = 'Some text'; var s = String.format('<div class="{0}">{1}</div>', cls, text); // s now contains the string: '<div class="my-class">Some text</div>' </code></pre> * @param {String} string The tokenized string to be formatted * @param {String} value1 The value to replace token {0} * @param {String} value2 Etc... * @return {String} The formatted string * @static */ format : function(format){ var args = Array.prototype.slice.call(arguments, 1); return format.replace(/\{(\d+)\}/g, function(m, i){ return args[i]; }); } }); /** * 4.字符串工具类,如果第一个参数等于当前字符串,把第二个参数的值赋给当前字符串;如果不等,把第一个参数的值赋给当前字符串。 */ String.prototype.toggle = function(value, other){ return this == value ? other : value; }; /** * 5.字符串工具类,去掉字符串左边和右边的空格。 */ String.prototype.trim = function(){ var re = /^\s+|\s+$/g; return function(){ return this.replace(re, ""); }; }(); /** * 6.添加到Number原型中constrain方法,判断当前数字是否在某个范围内,第一个参数表示下限,第二个参数表示上限。 */ Ext.applyIf(Number.prototype, { /** * Checks whether or not the current number is within a desired range. If the number is already within the * range it is returned, otherwise the min or max value is returned depending on which side of the range is * exceeded. Note that this method returns the constrained value but does not change the current number. * @param {Number} min The minimum number in the range * @param {Number} max The maximum number in the range * @return {Number} The constrained value if outside the range, otherwise the current value */ constrain : function(min, max){ return Math.min(Math.max(this, min), max); } }); /** * 7.添加到Array类原型中的方法。 * * 第一个方法判断特定对象是否在当前数组中,如果在,返回索引值;不在,返回-1. * * 第二个方法删除当前数组中的特定对象。返回变化后的数组;如果对象不在,什么也不做。 */ Ext.applyIf(Array.prototype, { /** * Checks whether or not the specified object exists in the array. * @param {Object} o The object to check for * @return {Number} The index of o in the array (or -1 if it is not found) */ indexOf : function(o){ for (var i = 0, len = this.length; i < len; i++){ if(this[i] == o) return i; } return -1; }, /** * Removes the specified object from the array. If the object is not found nothing happens. * @param {Object} o The object to remove * @return {Array} this array */ remove : function(o){ var index = this.indexOf(o); if(index != -1){ this.splice(index, 1); } return this; } }); /** * 8.添加到Date类原型中的方法getElapsed,返回特定时间与当前时间之间的毫秒数,结果是非负值。 * @param {} date * @return {} */ Date.prototype.getElapsed = function(date) { return Math.abs((date || new Date()).getTime()-this.getTime()); }; /** * 9.源码中L42到L634,定义了一个匿名函数并执行,定义了Ext类的公共属性和方法。 */ //覆盖方法,第一个参数表示原类,第二个参数是覆盖对象,把覆盖对象中的每一个属性赋值给原类的原型中。保证原类的所有实例都具有这些覆盖属性。 override = function(origclass, overrides){ if(overrides){ var p = origclass.prototype; for(var method in overrides){ p[method] = overrides[method]; } } } //继承方法, extend = function(){ // inline overrides var io = function(o){ for(var m in o){ this[m] = o[m]; } }; var oc = Object.prototype.constructor; return function(sb, sp, overrides){ if(typeof sp == 'object'){ overrides = sp; sp = sb; sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; } var F = function(){}, sbp, spp = sp.prototype; F.prototype = spp; sbp = sb.prototype = new F(); sbp.constructor=sb; sb.superclass=spp; if(spp.constructor == oc){ spp.constructor=sp; } sb.override = function(o){ Ext.override(sb, o); }; sbp.override = io; Ext.override(sb, overrides); sb.extend = function(o){Ext.extend(sb, o);}; return sb; }; }() 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |