~cdparra/gelee/trunk

« back to all changes in this revision

Viewing changes to webui/web/extjs/source/core/core/Ext.js

  • Committer: parra
  • Date: 2010-03-15 15:56:56 UTC
  • Revision ID: svn-v4:ac5bba68-f036-4e09-846e-8f32731cc928:trunk/gelee:1448
merged gelee at svn

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Ext JS Library 3.0 RC2
 
3
 * Copyright(c) 2006-2009, Ext JS, LLC.
 
4
 * licensing@extjs.com
 
5
 * 
 
6
 * http://extjs.com/license
 
7
 */
 
8
 
 
9
 
 
10
// for old browsers
 
11
window.undefined = window.undefined;
 
12
 
 
13
/**
 
14
 * @class Ext
 
15
 * Ext core utilities and functions.
 
16
 * @singleton
 
17
 */
 
18
 
 
19
Ext = {
 
20
    /**
 
21
     * The version of the framework
 
22
     * @type String
 
23
     */
 
24
    version: '3.0'
 
25
};
 
26
 
 
27
/**
 
28
 * Copies all the properties of config to obj.
 
29
 * @param {Object} obj The receiver of the properties
 
30
 * @param {Object} config The source of the properties
 
31
 * @param {Object} defaults A different object that will also be applied for default values
 
32
 * @return {Object} returns obj
 
33
 * @member Ext apply
 
34
 */
 
35
Ext.apply = function(o, c, defaults){
 
36
    // no "this" reference for friendly out of scope calls
 
37
    if (defaults) Ext.apply(o, defaults);
 
38
    if(o && c && typeof c == 'object'){
 
39
        for(var p in c){
 
40
            o[p] = c[p];
 
41
        }
 
42
    }
 
43
    return o;
 
44
};
 
45
 
 
46
(function(){
 
47
    var idSeed = 0,
 
48
        ua = navigator.userAgent.toLowerCase(),
 
49
        check = function(r){
 
50
            return r.test(ua);
 
51
        },
 
52
        isStrict = document.compatMode == "CSS1Compat",
 
53
        isOpera = check(/opera/),
 
54
        isChrome = check(/chrome/),
 
55
        isWebKit = check(/webkit/),
 
56
        isSafari = !isChrome && check(/safari/),
 
57
        isSafari3 = isSafari && check(/version\/3/),
 
58
        isSafari4 = isSafari && check(/version\/4/),
 
59
        isIE = !isOpera && check(/msie/),
 
60
        isIE7 = isIE && check(/msie 7/),
 
61
        isIE8 = isIE && check(/msie 8/),
 
62
        isGecko = !isWebKit && check(/gecko/),
 
63
        isGecko3 = isGecko && check(/rv:1\.9/),
 
64
        isBorderBox = isIE && !isStrict,
 
65
        isWindows = check(/windows|win32/),
 
66
        isMac = check(/macintosh|mac os x/),
 
67
        isAir = check(/adobeair/),
 
68
        isLinux = check(/linux/),
 
69
        isSecure = /^https/i.test(window.location.protocol);
 
70
 
 
71
    // remove css image flicker
 
72
    if(isIE && !(isIE7 || isIE8)){
 
73
        try{
 
74
            document.execCommand("BackgroundImageCache", false, true);
 
75
        }catch(e){}
 
76
    }
 
77
 
 
78
    Ext.apply(Ext, {
 
79
        /**
 
80
         * True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode
 
81
         * @type Boolean
 
82
         */
 
83
        isStrict : isStrict,
 
84
        /**
 
85
         * True if the page is running over SSL
 
86
         * @type Boolean
 
87
         */
 
88
        isSecure : isSecure,
 
89
        /**
 
90
         * True when the document is fully initialized and ready for action
 
91
         * @type Boolean
 
92
         */
 
93
        isReady : false,
 
94
 
 
95
        /**
 
96
         * True if the {@link Ext.Fx} Class is available
 
97
         * @type Boolean
 
98
         * @property enableFx
 
99
         */
 
100
 
 
101
        /**
 
102
         * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
 
103
         * @type Boolean
 
104
         */
 
105
        enableGarbageCollector : true,
 
106
 
 
107
        /**
 
108
         * True to automatically purge event listeners after uncaching an element (defaults to false).
 
109
         * Note: this only happens if {@link #enableGarbageCollector} is true.
 
110
         * @type Boolean
 
111
         */
 
112
        enableListenerCollection : false,
 
113
 
 
114
        /**
 
115
         * Indicates whether to use native browser parsing for JSON methods.
 
116
         * This option is ignored if the browser does not support native JSON methods.
 
117
         * <b>Note: Native JSON methods will not work with objects that have functions.
 
118
         * Also, property names must be quoted, otherwise the data will not parse.</b> (Defaults to false)
 
119
         * @type Boolean
 
120
         */
 
121
        USE_NATIVE_JSON : false,
 
122
 
 
123
        /**
 
124
         * Copies all the properties of config to obj if they don't already exist.
 
125
         * @param {Object} obj The receiver of the properties
 
126
         * @param {Object} config The source of the properties
 
127
         * @return {Object} returns obj
 
128
         */
 
129
        applyIf : function(o, c){
 
130
            if(o){
 
131
                for(var p in c){
 
132
                    if(Ext.isEmpty(o[p])){ o[p] = c[p]; }
 
133
                }
 
134
            }
 
135
            return o;
 
136
        },
 
137
 
 
138
        /**
 
139
         * Generates unique ids. If the element already has an id, it is unchanged
 
140
         * @param {Mixed} el (optional) The element to generate an id for
 
141
         * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
 
142
         * @return {String} The generated Id.
 
143
         */
 
144
        id : function(el, prefix){
 
145
            return (el = Ext.getDom(el) || {}).id = el.id || (prefix || "ext-gen") + (++idSeed);
 
146
        },
 
147
 
 
148
        /**
 
149
         * Extends one class with another class and optionally overrides members with the passed literal. This class
 
150
         * also adds the function "override()" to the class that can be used to override
 
151
         * members on an instance.
 
152
         * * <p>
 
153
         * This function also supports a 2-argument call in which the subclass's constructor is
 
154
         * not passed as an argument. In this form, the parameters are as follows:</p><p>
 
155
         * <div class="mdetail-params"><ul>
 
156
         * <li><code>superclass</code>
 
157
         * <div class="sub-desc">The class being extended</div></li>
 
158
         * <li><code>overrides</code>
 
159
         * <div class="sub-desc">A literal with members which are copied into the subclass's
 
160
         * prototype, and are therefore shared among all instances of the new class.<p>
 
161
         * This may contain a special member named <tt><b>constructor</b></tt>. This is used
 
162
         * to define the constructor of the new class, and is returned. If this property is
 
163
         * <i>not</i> specified, a constructor is generated and returned which just calls the
 
164
         * superclass's constructor passing on its parameters.</p></div></li>
 
165
         * </ul></div></p><p>
 
166
         * For example, to create a subclass of the Ext GridPanel:
 
167
         * <pre><code>
 
168
MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
 
169
    constructor: function(config) {
 
170
        // Your preprocessing here
 
171
        MyGridPanel.superclass.constructor.apply(this, arguments);
 
172
        // Your postprocessing here
 
173
    },
 
174
 
 
175
    yourMethod: function() {
 
176
        // etc.
 
177
    }
 
178
});
 
179
</code></pre>
 
180
         * </p>
 
181
         * @param {Function} subclass The class inheriting the functionality
 
182
         * @param {Function} superclass The class being extended
 
183
         * @param {Object} overrides (optional) A literal with members which are copied into the subclass's
 
184
         * prototype, and are therefore shared between all instances of the new class.
 
185
         * @return {Function} The subclass constructor.
 
186
         * @method extend
 
187
         */
 
188
        extend : function(){
 
189
            // inline overrides
 
190
            var io = function(o){
 
191
                for(var m in o){
 
192
                    this[m] = o[m];
 
193
                }
 
194
            };
 
195
            var oc = Object.prototype.constructor;
 
196
 
 
197
            return function(sb, sp, overrides){
 
198
                if(Ext.isObject(sp)){
 
199
                    overrides = sp;
 
200
                    sp = sb;
 
201
                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
 
202
                }
 
203
                var F = function(){},
 
204
                    sbp,
 
205
                    spp = sp.prototype;
 
206
 
 
207
                F.prototype = spp;
 
208
                sbp = sb.prototype = new F();
 
209
                sbp.constructor=sb;
 
210
                sb.superclass=spp;
 
211
                if(spp.constructor == oc){
 
212
                    spp.constructor=sp;
 
213
                }
 
214
                sb.override = function(o){
 
215
                    Ext.override(sb, o);
 
216
                };
 
217
                sbp.superclass = sbp.supr = (function(){
 
218
                    return spp;
 
219
                });
 
220
                sbp.override = io;
 
221
                Ext.override(sb, overrides);
 
222
                sb.extend = function(o){Ext.extend(sb, o);};
 
223
                return sb;
 
224
            };
 
225
        }(),
 
226
 
 
227
        /**
 
228
         * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
 
229
         * Usage:<pre><code>
 
230
Ext.override(MyClass, {
 
231
    newMethod1: function(){
 
232
        // etc.
 
233
    },
 
234
    newMethod2: function(foo){
 
235
        // etc.
 
236
    }
 
237
});
 
238
</code></pre>
 
239
         * @param {Object} origclass The class to override
 
240
         * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
 
241
         * containing one or more methods.
 
242
         * @method override
 
243
         */
 
244
        override : function(origclass, overrides){
 
245
            if(overrides){
 
246
                var p = origclass.prototype;
 
247
                Ext.apply(p, overrides);
 
248
                if(Ext.isIE && overrides.toString != origclass.toString){
 
249
                    p.toString = overrides.toString;
 
250
                }
 
251
            }
 
252
        },
 
253
 
 
254
        /**
 
255
         * Creates namespaces to be used for scoping variables and classes so that they are not global.
 
256
         * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
 
257
         * <pre><code>
 
258
Ext.namespace('Company', 'Company.data');
 
259
Ext.namespace('Company.data'); // equivalent and preferable to above syntax
 
260
Company.Widget = function() { ... }
 
261
Company.data.CustomStore = function(config) { ... }
 
262
</code></pre>
 
263
         * @param {String} namespace1
 
264
         * @param {String} namespace2
 
265
         * @param {String} etc
 
266
         * @method namespace
 
267
         */
 
268
        namespace : function(){
 
269
            var o, d;
 
270
            Ext.each(arguments, function(v) {
 
271
                d = v.split(".");
 
272
                o = window[d[0]] = window[d[0]] || {};
 
273
                Ext.each(d.slice(1), function(v2){
 
274
                    o = o[v2] = o[v2] || {};
 
275
                });
 
276
            });
 
277
            return o;
 
278
        },
 
279
 
 
280
        /**
 
281
         * 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.
 
282
         * @param {Object} o
 
283
         * @param {String} pre (optional) A prefix to add to the url encoded string
 
284
         * @return {String}
 
285
         */
 
286
        urlEncode: function(o, pre){
 
287
            var undef, buf = [], key, e = encodeURIComponent;
 
288
 
 
289
                for(key in o){
 
290
                    undef = typeof o[key] == 'undefined';
 
291
                    Ext.each(undef ? key : o[key], function(val, i){
 
292
                        buf.push("&", e(key), "=", (val != key || !undef) ? e(val) : "");
 
293
                    });
 
294
                }
 
295
                if(!pre){
 
296
                    buf.shift();
 
297
                    pre = "";
 
298
                }
 
299
                return pre + buf.join('');
 
300
        },
 
301
 
 
302
        /**
 
303
         * Takes an encoded URL and and converts it to an object. Example: <pre><code>
 
304
Ext.urlDecode("foo=1&bar=2"); // returns {foo: "1", bar: "2"}
 
305
Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2", "3", "4"]}
 
306
</code></pre>
 
307
         * @param {String} string
 
308
         * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
 
309
         * @return {Object} A literal with members
 
310
         */
 
311
        urlDecode : function(string, overwrite){
 
312
            var obj = {},
 
313
                pairs = string.split('&'),
 
314
                d = decodeURIComponent,
 
315
                name,
 
316
                value;
 
317
            Ext.each(pairs, function(pair) {
 
318
                pair = pair.split('=');
 
319
                name = d(pair[0]);
 
320
                value = d(pair[1]);
 
321
                obj[name] = overwrite || !obj[name] ? value :
 
322
                            [].concat(obj[name]).concat(value);
 
323
            });
 
324
            return obj;
 
325
        },
 
326
 
 
327
        /**
 
328
         * Converts any iterable (numeric indices and a length property) into a true array
 
329
         * Don't use this on strings. IE doesn't support "abc"[0] which this implementation depends on.
 
330
         * For strings, use this instead: "abc".match(/./g) => [a,b,c];
 
331
         * @param {Iterable} the iterable object to be turned into a true Array.
 
332
         * @return (Array) array
 
333
         */
 
334
        toArray : function(){
 
335
            return isIE ?
 
336
                function(a, i, j, res){
 
337
                    res = [];
 
338
                    Ext.each(a, function(v) {
 
339
                        res.push(v);
 
340
                    });
 
341
                    return res.slice(i || 0, j || res.length);
 
342
                } :
 
343
                function(a, i, j){
 
344
                    return Array.prototype.slice.call(a, i || 0, j || a.length);
 
345
                }
 
346
        }(),
 
347
 
 
348
        /**
 
349
         * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
 
350
         * passed array is not really an array, your function is called once with it.
 
351
         * The supplied function is called with (Object item, Number index, Array allItems).
 
352
         * @param {Array/NodeList/Mixed} array
 
353
         * @param {Function} fn
 
354
         * @param {Object} scope
 
355
         */
 
356
        each: function(array, fn, scope){
 
357
            if(Ext.isEmpty(array, true)){
 
358
                return;
 
359
            }
 
360
            if(typeof array.length == "undefined" || Ext.isPrimitive(array)){
 
361
                array = [array];
 
362
            }
 
363
            for(var i = 0, len = array.length; i < len; i++){
 
364
                if(fn.call(scope || array[i], array[i], i, array) === false){
 
365
                    return i;
 
366
                };
 
367
            }
 
368
        },
 
369
 
 
370
        /**
 
371
         * Return the dom node for the passed String (id), dom node, or Ext.Element.
 
372
         * Here are some examples:
 
373
         * <pre><code>
 
374
// gets dom node based on id
 
375
var elDom = Ext.getDom('elId');
 
376
// gets dom node based on the dom node
 
377
var elDom1 = Ext.getDom(elDom);
 
378
 
 
379
// If we don&#39;t know if we are working with an
 
380
// Ext.Element or a dom node use Ext.getDom
 
381
function(el){
 
382
    var dom = Ext.getDom(el);
 
383
    // do something with the dom node
 
384
}
 
385
         * </code></pre>
 
386
         * <b>Note</b>: the dom node to be found actually needs to exist (be rendered, etc)
 
387
         * when this method is called to be successful.
 
388
         * @param {Mixed} el
 
389
         * @return HTMLElement
 
390
         */
 
391
        getDom : function(el){
 
392
            if(!el || !document){
 
393
                return null;
 
394
            }
 
395
            return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
 
396
        },
 
397
 
 
398
        /**
 
399
         * Returns the current document body as an {@link Ext.Element}.
 
400
         * @return Ext.Element The document body
 
401
         */
 
402
        getBody : function(){
 
403
            return Ext.get(document.body || document.documentElement);
 
404
        },
 
405
 
 
406
        /**
 
407
         * Removes a DOM node from the document.  The body node will be ignored if passed in.
 
408
         * @param {HTMLElement} node The node to remove
 
409
         */
 
410
        removeNode : isIE ? function(){
 
411
            var d;
 
412
            return function(n){
 
413
                if(n && n.tagName != 'BODY'){
 
414
                    d = d || document.createElement('div');
 
415
                    d.appendChild(n);
 
416
                    d.innerHTML = '';
 
417
                }
 
418
            }
 
419
        }() : function(n){
 
420
            if(n && n.parentNode && n.tagName != 'BODY'){
 
421
                n.parentNode.removeChild(n);
 
422
            }
 
423
        },
 
424
 
 
425
        /**
 
426
         * <p>Returns true if the passed value is empty.</p>
 
427
         * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
 
428
         * <li>null</li>
 
429
         * <li>undefined</li>
 
430
         * <li>an empty array</li>
 
431
         * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
 
432
         * </ul></div>
 
433
         * @param {Mixed} value The value to test
 
434
         * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
 
435
         * @return {Boolean}
 
436
         */
 
437
        isEmpty : function(v, allowBlank){
 
438
            return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
 
439
        },
 
440
 
 
441
        /**
 
442
         * Returns true if the passed object is a JavaScript array, otherwise false.
 
443
         * @param {Object} object The object to test
 
444
         * @return {Boolean}
 
445
         */
 
446
        isArray : function(v){
 
447
            return Object.prototype.toString.apply(v) === '[object Array]';
 
448
        },
 
449
 
 
450
        /**
 
451
         * Returns true if the passed object is a JavaScript Object, otherwise false.
 
452
         * @param {Object} object The object to test
 
453
         * @return {Boolean}
 
454
         */
 
455
        isObject : function(v){
 
456
            return v && typeof v == "object";
 
457
        },
 
458
 
 
459
        /**
 
460
         * Returns true if the passed object is a JavaScript 'primitive', a string, number or boolean.
 
461
         * @param {Mixed} value The value to test
 
462
         * @return {Boolean}
 
463
         */
 
464
        isPrimitive : function(v){
 
465
            var t = typeof v;
 
466
            return t == 'string' || t == 'number' || t == 'boolean';
 
467
        },
 
468
 
 
469
        /**
 
470
         * Returns true if the passed object is a JavaScript Function, otherwise false.
 
471
         * @param {Object} object The object to test
 
472
         * @return {Boolean}
 
473
         */
 
474
        isFunction : function(v){
 
475
            return typeof v == "function";
 
476
        },
 
477
 
 
478
        /**
 
479
         * True if the detected browser is Opera.
 
480
         * @type Boolean
 
481
         */
 
482
        isOpera : isOpera,
 
483
        /**
 
484
         * True if the detected browser uses WebKit.
 
485
         * @type Boolean
 
486
         */
 
487
        isWebKit: isWebKit,
 
488
        /**
 
489
         * True if the detected browser is Chrome.
 
490
         * @type Boolean
 
491
         */
 
492
        isChrome : isChrome,
 
493
        /**
 
494
         * True if the detected browser is Safari.
 
495
         * @type Boolean
 
496
         */
 
497
        isSafari : isSafari,
 
498
        /**
 
499
         * True if the detected browser is Safari 3.x.
 
500
         * @type Boolean
 
501
         */
 
502
        isSafari3 : isSafari3,
 
503
        /**
 
504
         * True if the detected browser is Safari 4.x.
 
505
         * @type Boolean
 
506
         */
 
507
        isSafari4 : isSafari4,
 
508
        /**
 
509
         * True if the detected browser is Safari 2.x.
 
510
         * @type Boolean
 
511
         */
 
512
        isSafari2 : isSafari && !(isSafari3 || isSafari4),
 
513
        /**
 
514
         * True if the detected browser is Internet Explorer.
 
515
         * @type Boolean
 
516
         */
 
517
        isIE : isIE,
 
518
        /**
 
519
         * True if the detected browser is Internet Explorer 6.x.
 
520
         * @type Boolean
 
521
         */
 
522
        isIE6 : isIE && !isIE7 && !isIE8,
 
523
        /**
 
524
         * True if the detected browser is Internet Explorer 7.x.
 
525
         * @type Boolean
 
526
         */
 
527
        isIE7 : isIE7,
 
528
        /**
 
529
         * True if the detected browser is Internet Explorer 8.x.
 
530
         * @type Boolean
 
531
         */
 
532
        isIE8 : isIE8,
 
533
        /**
 
534
         * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
 
535
         * @type Boolean
 
536
         */
 
537
        isGecko : isGecko,
 
538
        /**
 
539
         * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
 
540
         * @type Boolean
 
541
         */
 
542
        isGecko2 : isGecko && !isGecko3,
 
543
        /**
 
544
         * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
 
545
         * @type Boolean
 
546
         */
 
547
        isGecko3 : isGecko3,
 
548
        /**
 
549
         * True if the detected browser is Internet Explorer running in non-strict mode.
 
550
         * @type Boolean
 
551
         */
 
552
        isBorderBox : isBorderBox,
 
553
        /**
 
554
         * True if the detected platform is Linux.
 
555
         * @type Boolean
 
556
         */
 
557
        isLinux : isLinux,
 
558
        /**
 
559
         * True if the detected platform is Windows.
 
560
         * @type Boolean
 
561
         */
 
562
        isWindows : isWindows,
 
563
        /**
 
564
         * True if the detected platform is Mac OS.
 
565
         * @type Boolean
 
566
         */
 
567
        isMac : isMac,
 
568
        /**
 
569
         * True if the detected platform is Adobe Air.
 
570
         * @type Boolean
 
571
         */
 
572
        isAir : isAir
 
573
    });
 
574
 
 
575
    /**
 
576
     * Creates namespaces to be used for scoping variables and classes so that they are not global.
 
577
     * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
 
578
     * <pre><code>
 
579
Ext.namespace('Company', 'Company.data');
 
580
Ext.namespace('Company.data'); // equivalent and preferable to above syntax
 
581
Company.Widget = function() { ... }
 
582
Company.data.CustomStore = function(config) { ... }
 
583
</code></pre>
 
584
     * @param {String} namespace1
 
585
     * @param {String} namespace2
 
586
     * @param {String} etc
 
587
     * @method namespace
 
588
     */
 
589
    Ext.ns = Ext.namespace;
 
590
})();
 
591
 
 
592
Ext.ns("Ext", "Ext.util", "Ext.lib", "Ext.data");
 
593
 
 
594
 
 
595
/**
 
596
 * @class Function
 
597
 * These functions are available on every Function object (any JavaScript function).
 
598
 */
 
599
Ext.apply(Function.prototype, {
 
600
     /**
 
601
     * Creates an interceptor function. The passed fcn is called before the original one. If it returns false,
 
602
     * the original one is not called. The resulting function returns the results of the original function.
 
603
     * The passed fcn is called with the parameters of the original function. Example usage:
 
604
     * <pre><code>
 
605
var sayHi = function(name){
 
606
    alert('Hi, ' + name);
 
607
}
 
608
 
 
609
sayHi('Fred'); // alerts "Hi, Fred"
 
610
 
 
611
// create a new function that validates input without
 
612
// directly modifying the original function:
 
613
var sayHiToFriend = sayHi.createInterceptor(function(name){
 
614
    return name == 'Brian';
 
615
});
 
616
 
 
617
sayHiToFriend('Fred');  // no alert
 
618
sayHiToFriend('Brian'); // alerts "Hi, Brian"
 
619
</code></pre>
 
620
     * @param {Function} fcn The function to call before the original
 
621
     * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
 
622
     * @return {Function} The new function
 
623
     */
 
624
    createInterceptor : function(fcn, scope){
 
625
        var method = this;
 
626
        return !Ext.isFunction(fcn) ?
 
627
                this :
 
628
                function() {
 
629
                    var me = this,
 
630
                        args = arguments;
 
631
                    fcn.target = me;
 
632
                    fcn.method = method;
 
633
                    return (fcn.apply(scope || me || window, args) !== false) ?
 
634
                            method.apply(me || window, args) :
 
635
                            null;
 
636
                };
 
637
    },
 
638
 
 
639
     /**
 
640
     * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
 
641
     * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code>
 
642
     * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the
 
643
     * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always
 
644
     * executes in the window scope.
 
645
     * <p>This method is required when you want to pass arguments to a callback function.  If no arguments
 
646
     * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn).
 
647
     * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function
 
648
     * would simply execute immediately when the code is parsed. Example usage:
 
649
     * <pre><code>
 
650
var sayHi = function(name){
 
651
    alert('Hi, ' + name);
 
652
}
 
653
 
 
654
// clicking the button alerts "Hi, Fred"
 
655
new Ext.Button({
 
656
    text: 'Say Hi',
 
657
    renderTo: Ext.getBody(),
 
658
    handler: sayHi.createCallback('Fred')
 
659
});
 
660
</code></pre>
 
661
     * @return {Function} The new function
 
662
    */
 
663
    createCallback : function(/*args...*/){
 
664
        // make args available, in function below
 
665
        var args = arguments,
 
666
            method = this;
 
667
        return function() {
 
668
            return method.apply(window, args);
 
669
        };
 
670
    },
 
671
 
 
672
    /**
 
673
     * Creates a delegate (callback) that sets the scope to obj.
 
674
     * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code>
 
675
     * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
 
676
     * callback points to obj. Example usage:
 
677
     * <pre><code>
 
678
var sayHi = function(name){
 
679
    // Note this use of "this.text" here.  This function expects to
 
680
    // execute within a scope that contains a text property.  In this
 
681
    // example, the "this" variable is pointing to the btn object that
 
682
    // was passed in createDelegate below.
 
683
    alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
 
684
}
 
685
 
 
686
var btn = new Ext.Button({
 
687
    text: 'Say Hi',
 
688
    renderTo: Ext.getBody()
 
689
});
 
690
 
 
691
// This callback will execute in the scope of the
 
692
// button instance. Clicking the button alerts
 
693
// "Hi, Fred. You clicked the "Say Hi" button."
 
694
btn.on('click', sayHi.createDelegate(btn, ['Fred']));
 
695
</code></pre>
 
696
     * @param {Object} obj (optional) The object for which the scope is set
 
697
     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
 
698
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
 
699
     *                                             if a number the args are inserted at the specified position
 
700
     * @return {Function} The new function
 
701
     */
 
702
    createDelegate : function(obj, args, appendArgs){
 
703
        var method = this;
 
704
        return function() {
 
705
            var callArgs = args || arguments;
 
706
            if (appendArgs === true){
 
707
                callArgs = Array.prototype.slice.call(arguments, 0);
 
708
                callArgs = callArgs.concat(args);
 
709
            }else if (typeof appendArgs == "number"){
 
710
                callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
 
711
                var applyArgs = [appendArgs, 0].concat(args); // create method call params
 
712
                Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
 
713
            }
 
714
            return method.apply(obj || window, callArgs);
 
715
        };
 
716
    },
 
717
 
 
718
    /**
 
719
     * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
 
720
     * <pre><code>
 
721
var sayHi = function(name){
 
722
    alert('Hi, ' + name);
 
723
}
 
724
 
 
725
// executes immediately:
 
726
sayHi('Fred');
 
727
 
 
728
// executes after 2 seconds:
 
729
sayHi.defer(2000, this, ['Fred']);
 
730
 
 
731
// this syntax is sometimes useful for deferring
 
732
// execution of an anonymous function:
 
733
(function(){
 
734
    alert('Anonymous');
 
735
}).defer(100);
 
736
</code></pre>
 
737
     * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
 
738
     * @param {Object} obj (optional) The object for which the scope is set
 
739
     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
 
740
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
 
741
     *                                             if a number the args are inserted at the specified position
 
742
     * @return {Number} The timeout id that can be used with clearTimeout
 
743
     */
 
744
    defer : function(millis, obj, args, appendArgs){
 
745
        var fn = this.createDelegate(obj, args, appendArgs);
 
746
        if(millis > 0){
 
747
            return setTimeout(fn, millis);
 
748
        }
 
749
        fn();
 
750
        return 0;
 
751
    }
 
752
});
 
753
 
 
754
/**
 
755
 * @class String
 
756
 * These functions are available on every String object.
 
757
 */
 
758
Ext.applyIf(String, {
 
759
    /**
 
760
     * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens.  Each
 
761
     * token must be unique, and must increment in the format {0}, {1}, etc.  Example usage:
 
762
     * <pre><code>
 
763
var cls = 'my-class', text = 'Some text';
 
764
var s = String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
 
765
// s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
 
766
     * </code></pre>
 
767
     * @param {String} string The tokenized string to be formatted
 
768
     * @param {String} value1 The value to replace token {0}
 
769
     * @param {String} value2 Etc...
 
770
     * @return {String} The formatted string
 
771
     * @static
 
772
     */
 
773
    format : function(format){
 
774
        var args = Ext.toArray(arguments, 1);
 
775
        return format.replace(/\{(\d+)\}/g, function(m, i){
 
776
            return args[i];
 
777
        });
 
778
    }
 
779
});
 
780
 
 
781
/**
 
782
 * @class Array
 
783
 */
 
784
Ext.applyIf(Array.prototype, {
 
785
    /**
 
786
     * Checks whether or not the specified object exists in the array.
 
787
     * @param {Object} o The object to check for
 
788
     * @return {Number} The index of o in the array (or -1 if it is not found)
 
789
     */
 
790
    indexOf : function(o){
 
791
       for (var i = 0, len = this.length; i < len; i++){
 
792
           if(this[i] == o) return i;
 
793
       }
 
794
       return -1;
 
795
    },
 
796
 
 
797
    /**
 
798
     * Removes the specified object from the array.  If the object is not found nothing happens.
 
799
     * @param {Object} o The object to remove
 
800
     * @return {Array} this array
 
801
     */
 
802
    remove : function(o){
 
803
       var index = this.indexOf(o);
 
804
       if(index != -1){
 
805
           this.splice(index, 1);
 
806
       }
 
807
       return this;
 
808
    }
 
809
});