Ext.js

/*
 * Ext JS Library 2.1
 * Copyright(c) 2006-2008, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

//Ext版本号
Ext = {version: '2.1'};
//兼容老版本浏览器
// for old browsers
window["undefined"] = window["undefined"];
/**
 * @class Ext
 * Ext core utilities and functions.
 * @singleton
 */
/**
 * Copies all the properties of config to obj.
 * @param {Object} obj The receiver of the properties
 * @param {Object} config The source of the properties
 * @param {Object} defaults A different object that will also be applied for default values
 * @return {Object} returns obj
 * @member Ext apply
 */
//复制增加c对象所有属性方法到o对象,(defaults也一样)
Ext.apply = function(o, c, defaults){
    if(defaults){
        // no "this" reference for friendly out of scope calls
     //this作用域
        Ext.apply(o, defaults);
    }
    if(o && c && typeof c == 'object'){
     //复制所有的属性,方法
        for(var p in c){
            o[p] = c[p];
        }
    }
    return o;
};
//这段代码采用闭包的方式,其优点主要就是对变量作用域范围的限定,
//防止与外部变量冲突,实现对程序较好的封装。
//这段对浏览器及系统平台的检测代码还是很值得我们去学习和借鉴的,
//相信这些都是经过ext相关人员精心测试过的。
//该段代码其实主要是为了解决IE7之前的浏览器的一个背景图片闪烁的bug(IE有时对同一张背景图片position切换时也会重新加载而产生闪烁)
(function(){
 //全局元素ID默认标记++
    var idSeed = 0;
    //浏览器信息IE7.0 XP : mozilla/4.0 (compatible; msie 7.0; windows nt 5.1; infopath.2)
    var ua = navigator.userAgent.toLowerCase();
    //渲染模式...浏览器IE,IE7,MAC,AIR等版本信息
    //渲染模式 标准兼容模式开启 CSS1Compat /标准兼容模式关闭 BackCompat
    var isStrict = document.compatMode == "CSS1Compat",
     //判断是否Opera浏览器
        isOpera = ua.indexOf("opera") > -1,
        //判断是否Safari浏览器
        isSafari = (/webkit|khtml/).test(ua),
        //判断是否Safari3浏览器
        isSafari3 = isSafari && ua.indexOf('webkit/5') != -1,
        //判断是否IE浏览器
        isIE = !isOpera && ua.indexOf("msie") > -1,
        //判断是否IE 7浏览器
        isIE7 = !isOpera && ua.indexOf("msie 7") > -1,
        //判断是否gecko浏览器
        isGecko = !isSafari && ua.indexOf("gecko") > -1,
        //IE 渲染模式
        isBorderBox = isIE && !isStrict,
        //判断是否windows操作系统
        isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
        //判断是否Macintosh操作系统
        isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
        //判断是否adobeair操作系统
        isAir = (ua.indexOf("adobeair") != -1),
        //判断是否linux操作系统
        isLinux = (ua.indexOf("linux") != -1),
        //判断是否使用https传输
        isSecure = window.location.href.toLowerCase().indexOf("https") === 0;

   
    // remove css image flicker
 //解决IE7之前的背景图片闪烁问题
 if(isIE && !isIE7){
        try{
            document.execCommand("BackgroundImageCache", false, true);
        }catch(e){}
    }

    //Ext增加版本,属性信息等
    Ext.apply(Ext, {
        /**
         * True if the browser is in strict mode
         * @type Boolean
         */
     //渲染模式
        isStrict : isStrict,
        /**
         * True if the page is running over SSL
         * @type Boolean
         */
        //SSL
        isSecure : isSecure,
        /**
         * True when the document is fully initialized and ready for action
         * @type Boolean
         */
        //初始
        isReady : false,

        /**
         * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
         * @type Boolean
         */
        //注意看下面的Ext的垃圾回收算法...
        enableGarbageCollector : true,

        /**
         * True to automatically purge event listeners after uncaching an element (defaults to false).
         * Note: this only happens if enableGarbageCollector is true.
         * @type Boolean
         */
        //注意Ext中对缓存机制....在缓存元素被删除之后,元素上面的监听器(元素上面可能绑定很多类似事件的监听器)一并会被删除掉
        enableListenerCollection:false,


        /**
         * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent
         * the IE insecure content warning (defaults to javascript:false).
         * @type String
         */
        //
        SSL_SECURE_URL : "javascript:false",

        /**
         * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images. (Defaults to
         * "http://extjs.com/s.gif" and you should change this to a URL on your server).
         * @type String
         */
        //空白css背景图片
        BLANK_IMAGE_URL : "http:/"+"/extjs.com/s.gif",

        /**
        * A reusable empty function
        * @property
         * @type Function
        */
        //一个占位符函数,就是用了指导某个函数上... ...prototype框架里面也专门定义了个 空函数 属性
        emptyFn : function(){},

        /**
         * Copies all the properties of config to obj if they don't already exist.
         * @param {Object} obj The receiver of the properties
         * @param {Object} config The source of the properties
         * @return {Object} returns obj
         */
        //复制增加对象c不同于对象o的属性方法到对象o
        applyIf : function(o, c){
            if(o && c){
                for(var p in c){
                    if(typeof o[p] == "undefined"){
                     o[p] = c[p];
                    }
                }
            }
            return o;
        },

        /**
         * Applies event listeners to elements by selectors when the document is ready.
         * The event name is specified with an @ suffix.
         * @param {Object} obj The list of behaviors to apply
         */
        /*
        <pre><code>
   Ext.addBehaviors({
       // add a listener for click on all anchors in element with id foo
       '#foo a@click' : function(e, t){
           // do something
       },
 
       // add the same listener to multiple selectors (separated by comma BEFORE the @)
       '#foo a, #bar span.some-class@mouseover' : function(){
           // do something
       }
   });
  </code></pre>
  */
        //增加元素绑定监听行为
        addBehaviors : function(o){
            if(!Ext.isReady){
                Ext.onReady(function(){
                    Ext.addBehaviors(o);
                });
                return;
            }
            //元素 '#foo a@click':function(){}
   //指定 #foo a 监听绑定事件click
   //应用 id,class元素,动作click mouseOver mouseDown
   //监听 on 等于 listener
            var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
            for(var b in o){
                var parts = b.split('@');
                if(parts[1]){ // for Object prototype breakers
                    var s = parts[0];
                    if(!cache[s]){
                     //根据#foo,#xx 获取元素对象
                     //selector(选择器)来定位一个dom节点
                        cache[s] = Ext.select(s);
                    }
                    //定义元素对象的事件动作:#foo click
                    cache[s].on(parts[1], o[b]);
                }
            }
            cache = null;
        },

        /**
         * Generates unique ids. If the element already has an id, it is unchanged
         * @param {Mixed} el (optional) The element to generate an id for
         * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
         * @return {String} The generated Id.
         */
        //对页面元素生成唯一id,如果该元素已存在id,则不会再生成
        id : function(el, prefix){
            prefix = prefix || "ext-gen";
            el = Ext.getDom(el);
            var id = prefix + (++idSeed);
            return el ? (el.id ? el.id : (el.id = id)) : id;
        },

        /**
         * Extends one class with another class and optionally overrides members with the passed literal. This class
         * also adds the function "override()" to the class that can be used to override
         * members on an instance.
         * * <p>
         * This function also supports a 2-argument call in which the subclass's constructor is
         * not passed as an argument. In this form, the parameters are as follows:</p><p>
         * <div class="mdetail-params"><ul>
         * <li><code>superclass</code>
         * <div class="sub-desc">The class being extended</div></li>
         * <li><code>overrides</code>
         * <div class="sub-desc">A literal with members which are copied into the subclass's
         * prototype, and are therefore shared among all instances of the new class.<p>
         * This may contain a special member named <tt><b>constructor</b></tt>. This is used
         * to define the constructor of the new class, and is returned. If this property is
         * <i>not</i> specified, a constructor is generated and returned which just calls the
         * superclass's constructor passing on its parameters.</p></div></li>
         * </ul></div></p><p>
         * For example, to create a subclass of the Ext GridPanel:
         * </p>
         * @param {Function} subclass The class inheriting the functionality
         * @param {Function} superclass The class being extended
         * @param {Object} overrides (optional) A literal with members which are copied into the subclass's
         * prototype, and are therefore shared between all instances of the new class.
         * @return {Function} The subclass constructor.
         * @method extend
         */
         /*
         <pre><code>
       MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
          constructor: function(config) {
              // Your preprocessing here
           MyGridPanel.superclass.constructor.apply(this, arguments);
              // Your postprocessing here
          },
          yourMethod: function() {
              // etc.
          }
      });
  </code></pre>
        */
        //Ext继承
        //extend是重要的函数了,OO的继承在Ext中靠它了
  //语法上使用上了个闭包
  //函数定义完之后,马上进行调用,并且返回了也是个函数
  //从该函数的实现上看,该函数值针对子类以及父类的prototype操作,难怪Ext要求要在子类的构造函数中进行这样的调用语句
  //Subclass.superclass.constructor.call(this,arguments);显示地拷贝父类中非prototype定义的属性
  //如果非prototype所定义的方法,将不会被overrides中的属性所覆盖.
  /**
  (转)
  1,关于F的用法
  使用F是为了避免对sb原型对象的操作,联动影响sp的原型对象.
  2,当typeof sp == "function"时
  sb的原型将被替换,不保留任何原型属性
  sb的superclass指向sp的原型对象
  3,当typeof sp == "object"时
  sb的原型属性将被保留
  sb的superclass指向自己的原型对象
  效果略等同于override
  另:
  1,apply,applyIf主要用于typeof == "object"时的对象操作
  2,override,extend主要用于typeof == "function"时的对象原型操作
  **/
        extend : function(){
            // inline overrides
         //复制对象o的属性方法到当前自己对象(即不是prototype属性方法不被覆盖)
            var io = function(o){
                for(var m in o){
                    this[m] = o[m];
                }
            };
            //object的原型的构造函数
            var oc = Object.prototype.constructor;
            return function(sb, sp, overrides){
             //sb:A,sp:B,overrides:
             //判断sp是不是对象
                if(typeof sp == 'object'){
                 //sp赋值overrides      
                    overrides = sp;
                    //sb赋值sp        
                    sp = sb;
                    //overrides的构造函数是不是object原型的构造函数
                    //是,复制所有参数到sp,sp赋值sb    
                    //不是,overrides.constructor赋值sb                  
                    //综结果sb:B类的构造函数/复制参数到A类函数 
                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
                }
                //空函数F
                var F = function(){},
                sbp,
                //sp的原型赋值spp        
                spp = sp.prototype;
                //spp赋值F的原型        
                F.prototype = spp;
                //创建F函数的实例赋值sb的原型,再赋值sbp   
                sbp = sb.prototype = new F();
                //sb赋值sbp的构造函数        
                sbp.constructor=sb;
                //spp赋值sb的父类        
                sb.superclass=spp;
                //spp的构造函数等于oc
                if(spp.constructor == oc){
                 //sp赋值spp的构造函数      
                    spp.constructor=sp;
                }
                //o重写sb的prototype,(重写prototype)
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                //o重写sbpn属性方法,(函数的属性方法,不是prototype)
                sbp.override = io;
                //overrides重写sb中的prototype
                Ext.override(sb, overrides);
                //sb的继承方法
                sb.extend = function(o){Ext.extend(sb, o);};
                //最后定义override/extend方法,扩展后面函数的覆盖/继承
                return sb;
            };
        }(),

        /**
         * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
         * Usage:
         * @param {Object} origclass The class to override
         * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
         * containing one or more methods.
         * @method override
         */
        /*
        <pre><code>
   Ext.override(MyClass, {
       newMethod1: function(){
           // etc.
       },
       newMethod2: function(foo){
           // etc.
       }
   });
   </code></pre>
   */
        //overrides重写origclass的方法
        override : function(origclass, overrides){
            if(overrides){
                var p = origclass.prototype;
                for(var method in overrides){
                    p[method] = overrides[method];
                }
            }
        },

        /**
         * Creates namespaces to be used for scoping variables and classes so that they are not global.  Usage:
         *
         * @param {String} namespace1
         * @param {String} namespace2
         * @param {String} etc
         * @method namespace
         */
        /*
  <pre><code>
   Ext.namespace('Company', 'Company.data');
   Company.Widget = function() { ... }
   Company.data.CustomStore = function(config) { ... }
  </code></pre>
         */
        //命名空间
        namespace : function(){
            var a=arguments, o=null, i, j, d, rt;
            for (i=0; i<a.length; ++i) {
                d=a[i].split(".");
                rt = d[0];
                eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
                for (j=1; j<d.length; ++j) {
                    o[d[j]]=o[d[j]] || {};
                    o=o[d[j]];
                }
            }
        },

        /**
         * Takes an object and converts it to an encoded URL. e.g. Ext.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2".  Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
         * @param {Object} o
         * @return {String}
         */
        //将对象转化为一个编码后的URL连接
        urlEncode : function(o){
            if(!o){
                return "";
            }
            var buf = [];
            for(var key in o){
                var ov = o[key], k = encodeURIComponent(key);
                var type = typeof ov;
                if(type == 'undefined'){
                    buf.push(k, "=&");
                }else if(type != "function" && type != "object"){
                    buf.push(k, "=", encodeURIComponent(ov), "&");
                }else if(Ext.isArray(ov)){
                    if (ov.length) {
                     for(var i = 0, len = ov.length; i < len; i++) {
                         buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
                     }
                 } else {
                     buf.push(k, "=&");
                 }
                }
            }
            buf.pop();
            return buf.join("");
        },

        /**
         * Takes an encoded URL and and converts it to an object. e.g. Ext.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
         * @param {String} string
         * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
         * @return {Object} A literal with members
         */
        //将一个URL连接解码为一个对象
        urlDecode : function(string, overwrite){
            if(!string || !string.length){
                return {};
            }
            var obj = {};
            var pairs = string.split('&');
            var pair, name, value;
            for(var i = 0, len = pairs.length; i < len; i++){
                pair = pairs[i].split('=');
                name = decodeURIComponent(pair[0]);
                value = decodeURIComponent(pair[1]);
                if(overwrite !== true){
                    if(typeof obj[name] == "undefined"){
                        obj[name] = value;
                    }else if(typeof obj[name] == "string"){
                        obj[name] = [obj[name]];
                        obj[name].push(value);
                    }else{
                        obj[name].push(value);
                    }
                }else{
                    obj[name] = value;
                }
            }
            return obj;
        },

        /**
         * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
         * passed array is not really an array, your function is called once with it.
         * The supplied function is called with (Object item, Number index, Array allItems).
         * @param {Array/NodeList/Mixed} array
         * @param {Function} fn
         * @param {Object} scope
         */
        //迭代一个数组,数组中每个成员都将调用一次所传函数, 直到函数返回false才停止执行
        each : function(array, fn, scope){
            if(!Ext.isArray(array)){
                array = [array];
            }
            for(var i = 0, len = array.length; i < len; i++){
                if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
            }
        },

        // deprecated
        //转为数组
        combine : function(){
            var as = arguments, l = as.length, r = [];
            for(var i = 0; i < l; i++){
                var a = as[i];
                if(Ext.isArray(a)){
                    r = r.concat(a);
                }else if(a.length !== undefined && !a.substr){
                    r = r.concat(Array.prototype.slice.call(a, 0));
                }else{
                    r.push(a);
                }
            }
            return r;
        },

        /**
         * Escapes the passed string for use in a regular expression
         * @param {String} str
         * @return {String}
         */
        //避免传递的字符串参数被正则表达式读取
        escapeRe : function(s) {
            return s.replace(/([.*+?^${}()|[/]])/g, "//$1");
        },

        // internal
        //回滚函数
        callback : function(cb, scope, args, delay){
            if(typeof cb == "function"){
                if(delay){
                    cb.defer(delay, scope, args || []);
                }else{
                    cb.apply(scope, args || []);
                }
            }
        },

        /**
         * Return the dom node for the passed string (id), dom node, or Ext.Element
         * @param {Mixed} el
         * @return HTMLElement
         */
        //返回dom对象,参数可以是 string (id),dom node,或Ext.Element
        getDom : function(el){
            if(!el || !document){
                return null;
            }
            return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
        },

        /**
        * Returns the current HTML document object as an {@link Ext.Element}.
        * @return Ext.Element The document
        */
        //返回当前HTML文档的{@link Ext.Element}类型
        getDoc : function(){
            return Ext.get(document);
        },

        /**
        * Returns the current document body as an {@link Ext.Element}.
        * @return Ext.Element The document body
        */
        //返回当前document.body的{@link Ext.Element}类型
        getBody : function(){
            return Ext.get(document.body || document.documentElement);
        },

        /**
        * Shorthand for {@link Ext.ComponentMgr#get}
        * @param {String} id
        * @return Ext.Component
        */
        //{@link Ext.ComponentMgr#get}的简写方式
        //获取Ext组件
        getCmp : function(id){
            return Ext.ComponentMgr.get(id);
        },

        /**
         * Utility method for validating that a value is numeric, returning the specified default value if it is not.
         * @param {Mixed} value Should be a number, but any type will be handled appropriately
         * @param {Number} defaultValue The value to return if the original value is non-numeric
         * @return {Number} Value, if numeric, else defaultValue
         */
        //验证某个值是否数字的一个辅助方法,若不是,返回指定的缺省值
        num : function(v, defaultValue){
            if(typeof v != 'number'){
                return defaultValue;
            }
            return v;
        },

        /**
         * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
         * DOM (if applicable) and calling their destroy functions (if available).  This method is primarily
         * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
         * {@link Ext.util.Observable} can be passed in.  Any number of elements and/or components can be
         * passed into this function in a single call as separate arguments.
         * @param {Mixed} arg1 An {@link Ext.Element} or {@link Ext.Component} to destroy
         * @param {Mixed} arg2 (optional)
         * @param {Mixed} etc... (optional)
         */
        //尝试去移除每个传入的对象,包括DOM,事件侦听者,并呼叫他们的destroy方法(如果存在)
        destroy : function(){
            for(var i = 0, a = arguments, len = a.length; i < len; i++) {
                var as = a[i];
                if(as){
              if(typeof as.destroy == 'function'){
                  as.destroy();
              }
              else if(as.dom){
                  as.removeAllListeners();
                  as.remove();
              }
                }
            }
        },

        /**
         * Removes a DOM node from the document.  The body node will be ignored if passed in.
         * @param {HTMLElement} node The node to remove
         */
        //移除结点
        removeNode : isIE ? function(){
            var d;
            return function(n){
                if(n && n.tagName != 'BODY'){
                    d = d || document.createElement('div');
                    d.appendChild(n);
                    d.innerHTML = '';
                }
            }
        }() : function(n){
            if(n && n.parentNode && n.tagName != 'BODY'){
                n.parentNode.removeChild(n);
            }
        },

        // inpired by a similar function in mootools library
        /**
         * Returns the type of object that is passed in. If the object passed in is null or undefined it
         * return false otherwise it returns one of the following values:<ul>
         * <li><b>string</b>: If the object passed is a string</li>
         * <li><b>number</b>: If the object passed is a number</li>
         * <li><b>boolean</b>: If the object passed is a boolean value</li>
         * <li><b>function</b>: If the object passed is a function reference</li>
         * <li><b>object</b>: If the object passed is an object</li>
         * <li><b>array</b>: If the object passed is an array</li>
         * <li><b>regexp</b>: If the object passed is a regular expression</li>
         * <li><b>element</b>: If the object passed is a DOM Element</li>
         * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
         * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
         * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
         * @param {Mixed} object
         * @return {String}
         */
        //返回参数类型的详细信息
        type : function(o){
            if(o === undefined || o === null){
                return false;
            }
            if(o.htmlElement){
                return 'element';
            }
            var t = typeof o;
            if(t == 'object' && o.nodeName) {
                switch(o.nodeType) {
                    case 1: return 'element';
                    case 3: return (//S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
                }
            }
            if(t == 'object' || t == 'function') {
                switch(o.constructor) {
                    case Array: return 'array';
                    case RegExp: return 'regexp';
                }
                if(typeof o.length == 'number' && typeof o.item == 'function') {
                    return 'nodelist';
                }
            }
            return t;
        },

        /**
         * Returns true if the passed value is null, undefined or an empty string (optional).
         * @param {Mixed} value The value to test
         * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
         * @return {Boolean}
         */
        //如果传入的值是null、undefined或空字符串,则返回true。(可选)
        isEmpty : function(v, allowBlank){
            return v === null || v === undefined || (!allowBlank ? v === '' : false);
        },

        //默认值
        value : function(v, defaultValue, allowBlank){
            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
        },

        /**
         * Returns true if the passed object is a JavaScript array, otherwise false.
         * @param {Object} The object to test
         * @return {Boolean}
         */
        //是否数组
  isArray : function(v){
   return v && typeof v.pop == 'function';
  },

  /**
         * Returns true if the passed object is a JavaScript date object, otherwise false.
         * @param {Object} The object to test
         * @return {Boolean}
         */
  //是否日期
  isDate : function(v){
   return v && typeof v.getFullYear == 'function';
  },

        /** @type Boolean */
        isOpera : isOpera,
        /** @type Boolean */
        isSafari : isSafari,
        /** @type Boolean */
        isSafari3 : isSafari3,
        /** @type Boolean */
        isSafari2 : isSafari && !isSafari3,
        /** @type Boolean */
        isIE : isIE,
        /** @type Boolean */
        isIE6 : isIE && !isIE7,
        /** @type Boolean */
        isIE7 : isIE7,
        /** @type Boolean */
        isGecko : isGecko,
        /** @type Boolean */
        isBorderBox : isBorderBox,
        /** @type Boolean */
        isLinux : isLinux,
        /** @type Boolean */
        isWindows : isWindows,
        /** @type Boolean */
        isMac : isMac,
        /** @type Boolean */
        isAir : isAir,

     /**
      * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
      * you may want to set this to true.
      * @type Boolean
      */
        useShims : ((isIE && !isIE7) || (isGecko && isMac))
    });

    // in intellij using keyword "namespace" causes parsing errors
    //命名
    Ext.ns = Ext.namespace;
})();

Ext.ns("Ext", "Ext.util", "Ext.grid", "Ext.dd", "Ext.tree", "Ext.data",
                "Ext.form", "Ext.menu", "Ext.state", "Ext.lib", "Ext.layout", "Ext.app", "Ext.ux");


/**
 * @class Function
 * These functions are available on every Function object (any JavaScript function).
 */
//Ext复制function.prototype函数.如:回调,委派,延迟,组合,拦截函数
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:
     *
     * @return {Function} The new function
    */
 /*
 <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>
 */
 //创建一个回调函数,该回调传递参数的形式为: arguments[0], arguments[1], arguments[2],
    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:
     * @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
     */
    /*
    <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>
 */
    //创建一个委派对象 (回调) ,该对象的作用域指向obj
    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:
     * @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
     */
    /*
 <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>
 */
    //延迟调用该函数。
    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:
     * @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
     */
    /*
    <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>
 */
    //创建一个组合函数,调用次序为:原函数 + 参数中的函数。
    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:
     * @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
     */
    /*
    <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>
 */
    //创建一个拦截器函数。 传递的参数fcn被原函数之前调用。 如果fcn的返回值为false,则原函数不会被调用
    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);
        };
    }
});

/**
 * @class String
 * These functions are available as static methods on the JavaScript String object.
 */
//Ext String增加属性方法
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:
     * @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
     */
    /*
    <pre><code>
  var s = String.leftPad('123', 5, '0');
  // s now contains the string: '00123'
 </code></pre>
 */
    //在字符串左边填充指定字符。这对于统一字符或日期标准格式非常有用
    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:
     * @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
     */
    /*
    <pre><code>
  var cls = 'my-class', text = 'Some text';
  var s = String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
  // s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
 </code></pre>
 */
    //定义带标记的字符串,并用自定义字符替换标记
    format : function(format){
        var args = Array.prototype.slice.call(arguments, 1);
        return format.replace(//{(/d+)/}/g, function(m, i){
            return args[i];
        });
    }
});

/**
 * Utility function that allows you to easily switch a string between two alternating values.  The passed value
 * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
 * they are already different, the first value passed in is returned.  Note that this method returns the new value
 * but does not change the current string.
 * @param {String} value The value to compare to the current string
 * @param {String} other The new value to use if the string already equals the first value passed in
 * @return {String} The new value
 */
/*
<pre><code>
 // alternate sort directions
 sort = sort.toggle('ASC', 'DESC');
 // instead of conditional logic:
 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
</code></pre>
*/
//比较并交换字符串的值
String.prototype.toggle = function(value, other){
    return this == value ? other : value;
};

/**
 * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
 * @return {String} The trimmed string
 */
/*
<pre><code>
 var s = '  foo bar  ';
 alert('-' + s + '-');         //alerts "- foo bar -"
 alert('-' + s.trim() + '-');  //alerts "-foo bar-"
</code></pre>
*/
//空转换
String.prototype.trim = function(){
    var re = /^/s+|/s+$/g;
    return function(){ return this.replace(re, ""); };
}();
/**
 * @class Number
 */
//Ext Number复制方法
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);
    }
});
/**
 * @class Array
 */
//Ext Array增加属性方法
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;
    }
});

/**
 Returns the number of milliseconds between this date and date
 @param {Date} date (optional) Defaults to now
 @return {Number} The diff in milliseconds
 @member Date getElapsed
 */
//返回date对象创建时间与现在时间的时间差,单位为毫秒
Date.prototype.getElapsed = function(date) {
 return Math.abs((date || new Date()).getTime()-this.getTime());
};

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Ext.js提供了一个方便的类Ext.Ajax来执行异步HTTP请求,也就是AJAX请求。以下是使用Ext.Ajax的示例代码: ```javascript Ext.Ajax.request({ url: 'your-url', method: 'GET', // HTTP请求方法,可以是'GET'、'POST'等 params: { key1: 'value1', key2: 'value2' }, // 请求参数,可以是对象或字符串 success: function(response, options) { // 请求成功的回调函数 console.log(response.responseText); }, failure: function(response, options) { // 请求失败的回调函数 console.log(response.status); } }); ``` 在上面的代码中,我们使用Ext.Ajax.request方法发起了一个GET请求,请求的URL为'your-url',请求参数为{ key1: 'value1', key2: 'value2' }。请求成功后,会执行success回调函数,打印出响应文本;请求失败后,会执行failure回调函数,打印出响应状态码。 ### 回答2: Ext.js是一个JavaScript框架,用于构建富客户端应用程序。它提供了诸多功能和组件,其中之一就是Ajax(Asynchronous JavaScript and XML)。 通过Ext.js的Ajax组件,我们可以使用JavaScript发送HTTP请求,并获取服务器返回的数据,而无需刷新整个页面。这使得我们能够动态更新页面内容,提升用户体验。 使用Ext.js的Ajax,我们可以通过多种方式发送请求,如GET、POST、PUT等。我们可以指定请求的URL、参数和请求类型。我们还可以设置回调函数,在服务器响应后对返回数据进行处理。这样,我们可以根据服务器的响应结果,动态更新页面上的内容或执行其他操作。 此外,Ext.js的Ajax还提供了强大的错误处理机制。当请求发生错误时,我们可以通过回调函数获知,并进行相应的处理。这使得我们能够更好地处理异常情况,保证应用程序的稳定性和可靠性。 总结来说,Ext.js的Ajax功能为我们提供了一种方便、灵活和强大的方式与服务器进行数据交互。它使得我们可以在客户端页面动态获取和更新数据,提升用户体验,同时也提高了我们开发程序的效率。 ### 回答3: Ext.js 是一个用于构建富客户端应用程序的 JavaScript 框架,它提供了丰富的组件和工具来简化开发流程。其中,AJAX 是 Ext.js 中重要的特性之一。 AJAX(Asynchronous JavaScript and XML)是一种异步通信技术,可以在不重新加载整个页面的情况下向服务器发送请求并获取响应。在 Ext.js 中,我们可以通过使用 Ext.Ajax 类来实现 AJAX 的功能。 通过 Ext.Ajax,我们可以发送 GET、POST、PUT、DELETE 等不同类型的请求,同时也可以设置请求的 URL、参数、请求头等。我们可以使用回调函数来处理服务器返回的数据。当请求成功时,可执行 success 回调函数;当请求失败时,可执行 failure 回调函数。 在 Ext.js 中,AJAX 可以帮助我们实现与后端服务器的数据交互,实现动态数据加载、表单提交、登录认证等功能。通过使用 AJAX,我们可以向服务器发送请求并处理响应,实现前端与后端的数据交互,用户体验更加流畅。 总之,Ext.js 提供的 AJAX 功能使得开发者可以更加方便地通过异步通信方式与后端服务器进行交互,减少页面加载时间,提升用户体验。同时,Ext.js 还提供了其他丰富的功能和组件,使得开发复杂的富客户端应用程序变得更加简单。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值