source: trunk/web/addons/job_monarch/lib/extjs-30/src/core/Ext-more.js @ 625

Last change on this file since 625 was 625, checked in by ramonb, 15 years ago

lib/extjs-30:

  • new ExtJS 3.0
File size: 24.0 KB
Line 
1/*!
2 * Ext JS Library 3.0.0
3 * Copyright(c) 2006-2009 Ext JS, LLC
4 * licensing@extjs.com
5 * http://www.extjs.com/license
6 */
7/**
8 * @class Ext
9 */
10
11Ext.ns("Ext.grid", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
12       "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
13    /**
14     * Namespace alloted for extensions to the framework.
15     * @property ux
16     * @type Object
17     */
18
19Ext.apply(Ext, function(){
20    var E = Ext, idSeed = 0;
21
22    return {
23        /**
24        * A reusable empty function
25        * @property
26        * @type Function
27        */
28        emptyFn : function(){},
29
30        /**
31         * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images.
32         * In older versions of IE, this defaults to "http://extjs.com/s.gif" and you should change this to a URL on your server.
33         * For other browsers it uses an inline data URL.
34         * @type String
35         */
36        BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 ?
37                            'http:/' + '/extjs.com/s.gif' :
38                            'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
39
40        extendX : function(supr, fn){
41            return Ext.extend(supr, fn(supr.prototype));
42        },
43
44        /**
45         * Returns the current HTML document object as an {@link Ext.Element}.
46         * @return Ext.Element The document
47         */
48        getDoc : function(){
49            return Ext.get(document);
50        },
51
52        /**
53         * Returns true if the passed object is a JavaScript date object, otherwise false.
54         * @param {Object} object The object to test
55         * @return {Boolean}
56         */
57        isDate : function(v){
58            return Object.prototype.toString.apply(v) === '[object Date]';
59        },
60
61        /**
62         * Utility method for validating that a value is numeric, returning the specified default value if it is not.
63         * @param {Mixed} value Should be a number, but any type will be handled appropriately
64         * @param {Number} defaultValue The value to return if the original value is non-numeric
65         * @return {Number} Value, if numeric, else defaultValue
66         */
67        num : function(v, defaultValue){
68            v = Number(v === null || typeof v == 'boolean'? NaN : v);
69            return isNaN(v)? defaultValue : v;
70        },
71
72        /**
73         * <p>Utility method for returning a default value if the passed value is empty.</p>
74         * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
75         * <li>null</li>
76         * <li>undefined</li>
77         * <li>an empty array</li>
78         * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
79         * </ul></div>
80         * @param {Mixed} value The value to test
81         * @param {Mixed} defaultValue The value to return if the original value is empty
82         * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
83         * @return {Mixed} value, if non-empty, else defaultValue
84         */
85        value : function(v, defaultValue, allowBlank){
86            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
87        },
88
89        /**
90         * Escapes the passed string for use in a regular expression
91         * @param {String} str
92         * @return {String}
93         */
94        escapeRe : function(s) {
95            return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
96        },
97
98        sequence : function(o, name, fn, scope){
99            o[name] = o[name].createSequence(fn, scope);
100        },
101
102        /**
103         * Applies event listeners to elements by selectors when the document is ready.
104         * The event name is specified with an <tt>&#64;</tt> suffix.
105         * <pre><code>
106Ext.addBehaviors({
107    // add a listener for click on all anchors in element with id foo
108    '#foo a&#64;click' : function(e, t){
109        // do something
110    },
111   
112    // add the same listener to multiple selectors (separated by comma BEFORE the &#64;)
113    '#foo a, #bar span.some-class&#64;mouseover' : function(){
114        // do something
115    }
116});
117         * </code></pre>
118         * @param {Object} obj The list of behaviors to apply
119         */
120        addBehaviors : function(o){
121            if(!Ext.isReady){
122                Ext.onReady(function(){
123                    Ext.addBehaviors(o);
124                });
125            } else {
126                var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
127                    parts,
128                    b,
129                    s;
130                for (b in o) {
131                    if ((parts = b.split('@'))[1]) { // for Object prototype breakers
132                        s = parts[0];
133                        if(!cache[s]){
134                            cache[s] = Ext.select(s);
135                        }
136                        cache[s].on(parts[1], o[b]);
137                    }
138                }
139                cache = null;
140            }
141        },
142
143
144        // deprecated
145        combine : function(){
146            var as = arguments, l = as.length, r = [];
147            for(var i = 0; i < l; i++){
148                var a = as[i];
149                if(Ext.isArray(a)){
150                    r = r.concat(a);
151                }else if(a.length !== undefined && !a.substr){
152                    r = r.concat(Array.prototype.slice.call(a, 0));
153                }else{
154                    r.push(a);
155                }
156            }
157            return r;
158        },
159
160        /**
161         * Copies a set of named properties fom the source object to the destination object.
162         * <p>example:<pre><code>
163ImageComponent = Ext.extend(Ext.BoxComponent, {
164    initComponent: function() {
165        this.autoEl = { tag: 'img' };
166        MyComponent.superclass.initComponent.apply(this, arguments);
167        this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
168    }
169});
170         * </code></pre>
171         * @param {Object} The destination object.
172         * @param {Object} The source object.
173         * @param {Array/String} Either an Array of property names, or a comma-delimited list
174         * of property names to copy.
175         * @return {Object} The modified object.
176        */
177        copyTo : function(dest, source, names){
178            if(typeof names == 'string'){
179                names = names.split(/[,;\s]/);
180            }
181            Ext.each(names, function(name){
182                if(source.hasOwnProperty(name)){
183                    dest[name] = source[name];
184                }
185            }, this);
186            return dest;
187        },
188
189        /**
190         * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
191         * DOM (if applicable) and calling their destroy functions (if available).  This method is primarily
192         * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
193         * {@link Ext.util.Observable} can be passed in.  Any number of elements and/or components can be
194         * passed into this function in a single call as separate arguments.
195         * @param {Mixed} arg1 An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
196         * @param {Mixed} arg2 (optional)
197         * @param {Mixed} etc... (optional)
198         */
199        destroy : function(){
200            Ext.each(arguments, function(arg){
201                if(arg){
202                    if(Ext.isArray(arg)){
203                        this.destroy.apply(this, arg);
204                    }else if(Ext.isFunction(arg.destroy)){
205                        arg.destroy();
206                    }else if(arg.dom){
207                        arg.remove();
208                    }   
209                }
210            }, this);
211        },
212
213        /**
214         * Attempts to destroy and then remove a set of named properties of the passed object.
215         * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
216         * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
217         * @param {Mixed} etc... More property names to destroy and remove.
218         */
219        destroyMembers : function(o, arg1, arg2, etc){
220            for(var i = 1, a = arguments, len = a.length; i < len; i++) {
221                Ext.destroy(o[a[i]]);
222                delete o[a[i]];
223            }
224        },
225
226        /**
227         * Creates a copy of the passed Array with falsy values removed.
228         * @param {Array/NodeList} arr The Array from which to remove falsy values.
229         * @return {Array} The new, compressed Array.
230         */
231        clean : function(arr){
232            var ret = [];
233            Ext.each(arr, function(v){
234                if(!!v){
235                    ret.push(v);
236                }
237            });
238            return ret;
239        },
240
241        /**
242         * Creates a copy of the passed Array, filtered to contain only unique values.
243         * @param {Array} arr The Array to filter
244         * @return {Array} The new Array containing unique values.
245         */
246        unique : function(arr){
247            var ret = [],
248                collect = {};
249
250            Ext.each(arr, function(v) {
251                if(!collect[v]){
252                    ret.push(v);
253                }
254                collect[v] = true;
255            });
256            return ret;
257        },
258
259        /**
260         * Recursively flattens into 1-d Array. Injects Arrays inline.
261         * @param {Array} arr The array to flatten
262         * @return {Array} The new, flattened array.
263         */
264        flatten : function(arr){
265            var worker = [];
266            function rFlatten(a) {
267                Ext.each(a, function(v) {
268                    if(Ext.isArray(v)){
269                        rFlatten(v);
270                    }else{
271                        worker.push(v);
272                    }
273                });
274                return worker;
275            }
276            return rFlatten(arr);
277        },
278
279        /**
280         * Returns the minimum value in the Array.
281         * @param {Array|NodeList} arr The Array from which to select the minimum value.
282         * @param {Function} comp (optional) a function to perform the comparision which determines minimization.
283         *                   If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
284         * @return {Object} The minimum value in the Array.
285         */
286        min : function(arr, comp){
287            var ret = arr[0];
288            comp = comp || function(a,b){ return a < b ? -1 : 1; };
289            Ext.each(arr, function(v) {
290                ret = comp(ret, v) == -1 ? ret : v;
291            });
292            return ret;
293        },
294
295        /**
296         * Returns the maximum value in the Array
297         * @param {Array|NodeList} arr The Array from which to select the maximum value.
298         * @param {Function} comp (optional) a function to perform the comparision which determines maximization.
299         *                   If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
300         * @return {Object} The maximum value in the Array.
301         */
302        max : function(arr, comp){
303            var ret = arr[0];
304            comp = comp || function(a,b){ return a > b ? 1 : -1; };
305            Ext.each(arr, function(v) {
306                ret = comp(ret, v) == 1 ? ret : v;
307            });
308            return ret;
309        },
310
311        /**
312         * Calculates the mean of the Array
313         * @param {Array} arr The Array to calculate the mean value of.
314         * @return {Number} The mean.
315         */
316        mean : function(arr){
317           return Ext.sum(arr) / arr.length;
318        },
319
320        /**
321         * Calculates the sum of the Array
322         * @param {Array} arr The Array to calculate the sum value of.
323         * @return {Number} The sum.
324         */
325        sum : function(arr){
326           var ret = 0;
327           Ext.each(arr, function(v) {
328               ret += v;
329           });
330           return ret;
331        },
332
333        /**
334         * Partitions the set into two sets: a true set and a false set.
335         * Example:
336         * Example2:
337         * <pre><code>
338// Example 1:
339Ext.partition([true, false, true, true, false]); // [[true, true, true], [false, false]]
340
341// Example 2:
342Ext.partition(
343    Ext.query("p"),
344    function(val){
345        return val.className == "class1"
346    }
347);
348// true are those paragraph elements with a className of "class1",
349// false set are those that do not have that className.
350         * </code></pre>
351         * @param {Array|NodeList} arr The array to partition
352         * @param {Function} truth (optional) a function to determine truth.  If this is omitted the element
353         *                   itself must be able to be evaluated for its truthfulness.
354         * @return {Array} [true<Array>,false<Array>]
355         */
356        partition : function(arr, truth){
357            var ret = [[],[]];
358            Ext.each(arr, function(v, i, a) {
359                ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
360            });
361            return ret;
362        },
363
364        /**
365         * Invokes a method on each item in an Array.
366         * <pre><code>
367// Example:
368Ext.invoke(Ext.query("p"), "getAttribute", "id");
369// [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
370         * </code></pre>
371         * @param {Array|NodeList} arr The Array of items to invoke the method on.
372         * @param {String} methodName The method name to invoke.
373         * @param {Anything} ... Arguments to send into the method invocation.
374         * @return {Array} The results of invoking the method on each item in the array.
375         */
376        invoke : function(arr, methodName){
377            var ret = [],
378                args = Array.prototype.slice.call(arguments, 2);
379            Ext.each(arr, function(v,i) {
380                if (v && typeof v[methodName] == "function") {
381                    ret.push(v[methodName].apply(v, args));
382                } else {
383                    ret.push(undefined);
384                }
385            });
386            return ret;
387        },
388
389        /**
390         * Plucks the value of a property from each item in the Array
391         * <pre><code>
392// Example:
393Ext.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
394         * </code></pre>
395         * @param {Array|NodeList} arr The Array of items to pluck the value from.
396         * @param {String} prop The property name to pluck from each element.
397         * @return {Array} The value from each item in the Array.
398         */
399        pluck : function(arr, prop){
400            var ret = [];
401            Ext.each(arr, function(v) {
402                ret.push( v[prop] );
403            });
404            return ret;
405        },
406
407        /**
408         * <p>Zips N sets together.</p>
409         * <pre><code>
410// Example 1:
411Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
412// Example 2:
413Ext.zip(
414    [ "+", "-", "+"],
415    [  12,  10,  22],
416    [  43,  15,  96],
417    function(a, b, c){
418        return "$" + a + "" + b + "." + c
419    }
420); // ["$+12.43", "$-10.15", "$+22.96"]
421         * </code></pre>
422         * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
423         * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
424         * @return {Array} The zipped set.
425         */
426        zip : function(){
427            var parts = Ext.partition(arguments, function( val ){ return !Ext.isFunction(val); }),
428                arrs = parts[0],
429                fn = parts[1][0],
430                len = Ext.max(Ext.pluck(arrs, "length")),
431                ret = [];
432
433            for (var i = 0; i < len; i++) {
434                ret[i] = [];
435                if(fn){
436                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
437                }else{
438                    for (var j = 0, aLen = arrs.length; j < aLen; j++){
439                        ret[i].push( arrs[j][i] );
440                    }
441                }
442            }
443            return ret;
444        },
445
446        /**
447         * This is shorthand reference to {@link Ext.ComponentMgr#get}.
448         * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
449         * @param {String} id The component {@link Ext.Component#id id}
450         * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a
451         * Class was found.
452        */
453        getCmp : function(id){
454            return Ext.ComponentMgr.get(id);
455        },
456
457        /**
458         * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
459         * you may want to set this to true.
460         * @type Boolean
461         */
462        useShims: E.isIE6 || (E.isMac && E.isGecko2),
463
464        // inpired by a similar function in mootools library
465        /**
466         * Returns the type of object that is passed in. If the object passed in is null or undefined it
467         * return false otherwise it returns one of the following values:<div class="mdetail-params"><ul>
468         * <li><b>string</b>: If the object passed is a string</li>
469         * <li><b>number</b>: If the object passed is a number</li>
470         * <li><b>boolean</b>: If the object passed is a boolean value</li>
471         * <li><b>date</b>: If the object passed is a Date object</li>
472         * <li><b>function</b>: If the object passed is a function reference</li>
473         * <li><b>object</b>: If the object passed is an object</li>
474         * <li><b>array</b>: If the object passed is an array</li>
475         * <li><b>regexp</b>: If the object passed is a regular expression</li>
476         * <li><b>element</b>: If the object passed is a DOM Element</li>
477         * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
478         * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
479         * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
480         * </ul></div>
481         * @param {Mixed} object
482         * @return {String}
483         */
484        type : function(o){
485            if(o === undefined || o === null){
486                return false;
487            }
488            if(o.htmlElement){
489                return 'element';
490            }
491            var t = typeof o;
492            if(t == 'object' && o.nodeName) {
493                switch(o.nodeType) {
494                    case 1: return 'element';
495                    case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
496                }
497            }
498            if(t == 'object' || t == 'function') {
499                switch(o.constructor) {
500                    case Array: return 'array';
501                    case RegExp: return 'regexp';
502                    case Date: return 'date';
503                }
504                if(typeof o.length == 'number' && typeof o.item == 'function') {
505                    return 'nodelist';
506                }
507            }
508            return t;
509        },
510
511        intercept : function(o, name, fn, scope){
512            o[name] = o[name].createInterceptor(fn, scope);
513        },
514
515        // internal
516        callback : function(cb, scope, args, delay){
517            if(Ext.isFunction(cb)){
518                if(delay){
519                    cb.defer(delay, scope, args || []);
520                }else{
521                    cb.apply(scope, args || []);
522                }
523            }
524        }
525    };
526}());
527
528/**
529 * @class Function
530 * These functions are available on every Function object (any JavaScript function).
531 */
532Ext.apply(Function.prototype, {
533    /**
534     * Create a combined function call sequence of the original function + the passed function.
535     * The resulting function returns the results of the original function.
536     * The passed fcn is called with the parameters of the original function. Example usage:
537     * <pre><code>
538var sayHi = function(name){
539    alert('Hi, ' + name);
540}
541
542sayHi('Fred'); // alerts "Hi, Fred"
543
544var sayGoodbye = sayHi.createSequence(function(name){
545    alert('Bye, ' + name);
546});
547
548sayGoodbye('Fred'); // both alerts show
549</code></pre>
550     * @param {Function} fcn The function to sequence
551     * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
552     * @return {Function} The new function
553     */
554    createSequence : function(fcn, scope){
555        var method = this;
556        return !Ext.isFunction(fcn) ?
557                this :
558                function(){
559                    var retval = method.apply(this || window, arguments);
560                    fcn.apply(scope || this || window, arguments);
561                    return retval;
562                };
563    }
564});
565
566
567/**
568 * @class String
569 * These functions are available as static methods on the JavaScript String object.
570 */
571Ext.applyIf(String, {
572
573    /**
574     * Escapes the passed string for ' and \
575     * @param {String} string The string to escape
576     * @return {String} The escaped string
577     * @static
578     */
579    escape : function(string) {
580        return string.replace(/('|\\)/g, "\\$1");
581    },
582
583    /**
584     * Pads the left side of a string with a specified character.  This is especially useful
585     * for normalizing number and date strings.  Example usage:
586     * <pre><code>
587var s = String.leftPad('123', 5, '0');
588// s now contains the string: '00123'
589     * </code></pre>
590     * @param {String} string The original string
591     * @param {Number} size The total length of the output string
592     * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
593     * @return {String} The padded string
594     * @static
595     */
596    leftPad : function (val, size, ch) {
597        var result = String(val);
598        if(!ch) {
599            ch = " ";
600        }
601        while (result.length < size) {
602            result = ch + result;
603        }
604        return result;
605    }
606});
607
608/**
609 * Utility function that allows you to easily switch a string between two alternating values.  The passed value
610 * is compared to the current string, and if they are equal, the other value that was passed in is returned.  If
611 * they are already different, the first value passed in is returned.  Note that this method returns the new value
612 * but does not change the current string.
613 * <pre><code>
614// alternate sort directions
615sort = sort.toggle('ASC', 'DESC');
616
617// instead of conditional logic:
618sort = (sort == 'ASC' ? 'DESC' : 'ASC');
619</code></pre>
620 * @param {String} value The value to compare to the current string
621 * @param {String} other The new value to use if the string already equals the first value passed in
622 * @return {String} The new value
623 */
624String.prototype.toggle = function(value, other){
625    return this == value ? other : value;
626};
627
628/**
629 * Trims whitespace from either end of a string, leaving spaces within the string intact.  Example:
630 * <pre><code>
631var s = '  foo bar  ';
632alert('-' + s + '-');         //alerts "- foo bar -"
633alert('-' + s.trim() + '-');  //alerts "-foo bar-"
634</code></pre>
635 * @return {String} The trimmed string
636 */
637String.prototype.trim = function(){
638    var re = /^\s+|\s+$/g;
639    return function(){ return this.replace(re, ""); };
640}();
641
642// here to prevent dependency on Date.js
643/**
644 Returns the number of milliseconds between this date and date
645 @param {Date} date (optional) Defaults to now
646 @return {Number} The diff in milliseconds
647 @member Date getElapsed
648 */
649Date.prototype.getElapsed = function(date) {
650    return Math.abs((date || new Date()).getTime()-this.getTime());
651};
652
653
654/**
655 * @class Number
656 */
657Ext.applyIf(Number.prototype, {
658    /**
659     * Checks whether or not the current number is within a desired range.  If the number is already within the
660     * range it is returned, otherwise the min or max value is returned depending on which side of the range is
661     * exceeded.  Note that this method returns the constrained value but does not change the current number.
662     * @param {Number} min The minimum number in the range
663     * @param {Number} max The maximum number in the range
664     * @return {Number} The constrained value if outside the range, otherwise the current value
665     */
666    constrain : function(min, max){
667        return Math.min(Math.max(this, min), max);
668    }
669});
Note: See TracBrowser for help on using the repository browser.