2
* Ext JS Library 3.0 RC2
3
* Copyright(c) 2006-2009, Ext JS, LLC.
6
* http://extjs.com/license
11
window.undefined = window.undefined;
15
* Ext core utilities and functions.
21
* The version of the framework
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
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'){
48
ua = navigator.userAgent.toLowerCase(),
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);
71
// remove css image flicker
72
if(isIE && !(isIE7 || isIE8)){
74
document.execCommand("BackgroundImageCache", false, true);
80
* True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode
85
* True if the page is running over SSL
90
* True when the document is fully initialized and ready for action
96
* True if the {@link Ext.Fx} Class is available
102
* True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
105
enableGarbageCollector : true,
108
* True to automatically purge event listeners after uncaching an element (defaults to false).
109
* Note: this only happens if {@link #enableGarbageCollector} is true.
112
enableListenerCollection : false,
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)
121
USE_NATIVE_JSON : false,
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
129
applyIf : function(o, c){
132
if(Ext.isEmpty(o[p])){ o[p] = c[p]; }
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.
144
id : function(el, prefix){
145
return (el = Ext.getDom(el) || {}).id = el.id || (prefix || "ext-gen") + (++idSeed);
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.
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>
166
* For example, to create a subclass of the Ext GridPanel:
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
175
yourMethod: function() {
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.
190
var io = function(o){
195
var oc = Object.prototype.constructor;
197
return function(sb, sp, overrides){
198
if(Ext.isObject(sp)){
201
sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
203
var F = function(){},
208
sbp = sb.prototype = new F();
211
if(spp.constructor == oc){
214
sb.override = function(o){
217
sbp.superclass = sbp.supr = (function(){
221
Ext.override(sb, overrides);
222
sb.extend = function(o){Ext.extend(sb, o);};
228
* Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
230
Ext.override(MyClass, {
231
newMethod1: function(){
234
newMethod2: function(foo){
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.
244
override : function(origclass, overrides){
246
var p = origclass.prototype;
247
Ext.apply(p, overrides);
248
if(Ext.isIE && overrides.toString != origclass.toString){
249
p.toString = overrides.toString;
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:
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) { ... }
263
* @param {String} namespace1
264
* @param {String} namespace2
265
* @param {String} etc
268
namespace : function(){
270
Ext.each(arguments, function(v) {
272
o = window[d[0]] = window[d[0]] || {};
273
Ext.each(d.slice(1), function(v2){
274
o = o[v2] = o[v2] || {};
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.
283
* @param {String} pre (optional) A prefix to add to the url encoded string
286
urlEncode: function(o, pre){
287
var undef, buf = [], key, e = encodeURIComponent;
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) : "");
299
return pre + buf.join('');
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"]}
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
311
urlDecode : function(string, overwrite){
313
pairs = string.split('&'),
314
d = decodeURIComponent,
317
Ext.each(pairs, function(pair) {
318
pair = pair.split('=');
321
obj[name] = overwrite || !obj[name] ? value :
322
[].concat(obj[name]).concat(value);
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
334
toArray : function(){
336
function(a, i, j, res){
338
Ext.each(a, function(v) {
341
return res.slice(i || 0, j || res.length);
344
return Array.prototype.slice.call(a, i || 0, j || a.length);
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
356
each: function(array, fn, scope){
357
if(Ext.isEmpty(array, true)){
360
if(typeof array.length == "undefined" || Ext.isPrimitive(array)){
363
for(var i = 0, len = array.length; i < len; i++){
364
if(fn.call(scope || array[i], array[i], i, array) === false){
371
* Return the dom node for the passed String (id), dom node, or Ext.Element.
372
* Here are some examples:
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);
379
// If we don't know if we are working with an
380
// Ext.Element or a dom node use Ext.getDom
382
var dom = Ext.getDom(el);
383
// do something with the dom node
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.
389
* @return HTMLElement
391
getDom : function(el){
392
if(!el || !document){
395
return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
399
* Returns the current document body as an {@link Ext.Element}.
400
* @return Ext.Element The document body
402
getBody : function(){
403
return Ext.get(document.body || document.documentElement);
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
410
removeNode : isIE ? function(){
413
if(n && n.tagName != 'BODY'){
414
d = d || document.createElement('div');
420
if(n && n.parentNode && n.tagName != 'BODY'){
421
n.parentNode.removeChild(n);
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>
430
* <li>an empty array</li>
431
* <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
433
* @param {Mixed} value The value to test
434
* @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
437
isEmpty : function(v, allowBlank){
438
return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
442
* Returns true if the passed object is a JavaScript array, otherwise false.
443
* @param {Object} object The object to test
446
isArray : function(v){
447
return Object.prototype.toString.apply(v) === '[object Array]';
451
* Returns true if the passed object is a JavaScript Object, otherwise false.
452
* @param {Object} object The object to test
455
isObject : function(v){
456
return v && typeof v == "object";
460
* Returns true if the passed object is a JavaScript 'primitive', a string, number or boolean.
461
* @param {Mixed} value The value to test
464
isPrimitive : function(v){
466
return t == 'string' || t == 'number' || t == 'boolean';
470
* Returns true if the passed object is a JavaScript Function, otherwise false.
471
* @param {Object} object The object to test
474
isFunction : function(v){
475
return typeof v == "function";
479
* True if the detected browser is Opera.
484
* True if the detected browser uses WebKit.
489
* True if the detected browser is Chrome.
494
* True if the detected browser is Safari.
499
* True if the detected browser is Safari 3.x.
502
isSafari3 : isSafari3,
504
* True if the detected browser is Safari 4.x.
507
isSafari4 : isSafari4,
509
* True if the detected browser is Safari 2.x.
512
isSafari2 : isSafari && !(isSafari3 || isSafari4),
514
* True if the detected browser is Internet Explorer.
519
* True if the detected browser is Internet Explorer 6.x.
522
isIE6 : isIE && !isIE7 && !isIE8,
524
* True if the detected browser is Internet Explorer 7.x.
529
* True if the detected browser is Internet Explorer 8.x.
534
* True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
539
* True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
542
isGecko2 : isGecko && !isGecko3,
544
* True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
549
* True if the detected browser is Internet Explorer running in non-strict mode.
552
isBorderBox : isBorderBox,
554
* True if the detected platform is Linux.
559
* True if the detected platform is Windows.
562
isWindows : isWindows,
564
* True if the detected platform is Mac OS.
569
* True if the detected platform is Adobe Air.
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:
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) { ... }
584
* @param {String} namespace1
585
* @param {String} namespace2
586
* @param {String} etc
589
Ext.ns = Ext.namespace;
592
Ext.ns("Ext", "Ext.util", "Ext.lib", "Ext.data");
597
* These functions are available on every Function object (any JavaScript function).
599
Ext.apply(Function.prototype, {
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:
605
var sayHi = function(name){
606
alert('Hi, ' + name);
609
sayHi('Fred'); // alerts "Hi, Fred"
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';
617
sayHiToFriend('Fred'); // no alert
618
sayHiToFriend('Brian'); // alerts "Hi, Brian"
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
624
createInterceptor : function(fcn, scope){
626
return !Ext.isFunction(fcn) ?
633
return (fcn.apply(scope || me || window, args) !== false) ?
634
method.apply(me || window, args) :
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:
650
var sayHi = function(name){
651
alert('Hi, ' + name);
654
// clicking the button alerts "Hi, Fred"
657
renderTo: Ext.getBody(),
658
handler: sayHi.createCallback('Fred')
661
* @return {Function} The new function
663
createCallback : function(/*args...*/){
664
// make args available, in function below
665
var args = arguments,
668
return method.apply(window, args);
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:
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.');
686
var btn = new Ext.Button({
688
renderTo: Ext.getBody()
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']));
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
702
createDelegate : function(obj, args, appendArgs){
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
714
return method.apply(obj || window, callArgs);
719
* Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
721
var sayHi = function(name){
722
alert('Hi, ' + name);
725
// executes immediately:
728
// executes after 2 seconds:
729
sayHi.defer(2000, this, ['Fred']);
731
// this syntax is sometimes useful for deferring
732
// execution of an anonymous function:
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
744
defer : function(millis, obj, args, appendArgs){
745
var fn = this.createDelegate(obj, args, appendArgs);
747
return setTimeout(fn, millis);
756
* These functions are available on every String object.
758
Ext.applyIf(String, {
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:
763
var cls = 'my-class', text = 'Some text';
764
var s = String.format('<div class="{0}">{1}</div>', cls, text);
765
// s now contains the string: '<div class="my-class">Some text</div>'
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
773
format : function(format){
774
var args = Ext.toArray(arguments, 1);
775
return format.replace(/\{(\d+)\}/g, function(m, i){
784
Ext.applyIf(Array.prototype, {
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)
790
indexOf : function(o){
791
for (var i = 0, len = this.length; i < len; i++){
792
if(this[i] == o) return i;
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
802
remove : function(o){
803
var index = this.indexOf(o);
805
this.splice(index, 1);