/ext-4.1.0_b3/src/core/src/Ext-more.js
JavaScript | 1190 lines | 489 code | 122 blank | 579 comment | 168 complexity | ccae3db3a298e56b4cf71c7520614537 MD5 | raw file
1/**
2 * @class Ext
3 *
4 * The Ext namespace (global object) encapsulates all classes, singletons, and
5 * utility methods provided by Sencha's libraries.
6 *
7 * Most user interface Components are at a lower level of nesting in the namespace,
8 * but many common utility functions are provided as direct properties of the Ext namespace.
9 *
10 * Also many frequently used methods from other classes are provided as shortcuts
11 * within the Ext namespace. For example {@link Ext#getCmp Ext.getCmp} aliases
12 * {@link Ext.ComponentManager#get Ext.ComponentManager.get}.
13 *
14 * Many applications are initiated with {@link Ext#onReady Ext.onReady} which is
15 * called once the DOM is ready. This ensures all scripts have been loaded,
16 * preventing dependency issues. For example:
17 *
18 * Ext.onReady(function(){
19 * new Ext.Component({
20 * renderTo: document.body,
21 * html: 'DOM ready!'
22 * });
23 * });
24 *
25 * For more information about how to use the Ext classes, see:
26 *
27 * - <a href="http://www.sencha.com/learn/">The Learning Center</a>
28 * - <a href="http://www.sencha.com/learn/Ext_FAQ">The FAQ</a>
29 * - <a href="http://www.sencha.com/forum/">The forums</a>
30 *
31 * @singleton
32 */
33Ext.apply(Ext, {
34 userAgent: navigator.userAgent.toLowerCase(),
35 cache: {},
36 idSeed: 1000,
37 windowId: 'ext-window',
38 documentId: 'ext-document',
39
40 /**
41 * True when the document is fully initialized and ready for action
42 */
43 isReady: false,
44
45 /**
46 * True to automatically uncache orphaned Ext.Elements periodically
47 */
48 enableGarbageCollector: true,
49
50 /**
51 * True to automatically purge event listeners during garbageCollection.
52 */
53 enableListenerCollection: true,
54
55 /**
56 * Generates unique ids. If the element already has an id, it is unchanged
57 * @param {HTMLElement/Ext.Element} [el] The element to generate an id for
58 * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
59 * @return {String} The generated Id.
60 */
61 id: function(el, prefix) {
62 var me = this,
63 sandboxPrefix = '';
64 el = Ext.getDom(el, true) || {};
65 if (el === document) {
66 el.id = me.documentId;
67 }
68 else if (el === window) {
69 el.id = me.windowId;
70 }
71 if (!el.id) {
72 if (me.isSandboxed) {
73 sandboxPrefix = Ext.sandboxName.toLowerCase() + '-';
74 }
75 el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
76 }
77 return el.id;
78 },
79
80 /**
81 * Returns the current document body as an {@link Ext.Element}.
82 * @return Ext.Element The document body
83 */
84 getBody: function() {
85 var body;
86 return function() {
87 return body || (body = Ext.get(document.body));
88 };
89 }(),
90
91 /**
92 * Returns the current document head as an {@link Ext.Element}.
93 * @return Ext.Element The document head
94 * @method
95 */
96 getHead: function() {
97 var head;
98 return function() {
99 return head || (head = Ext.get(document.getElementsByTagName("head")[0]));
100 };
101 }(),
102
103 /**
104 * Returns the current HTML document object as an {@link Ext.Element}.
105 * @return Ext.Element The document
106 */
107 getDoc: function() {
108 var doc;
109 return function() {
110 return doc || (doc = Ext.get(document));
111 };
112 }(),
113
114 /**
115 * This is shorthand reference to {@link Ext.ComponentManager#get}.
116 * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
117 *
118 * @param {String} id The component {@link Ext.Component#id id}
119 * @return Ext.Component The Component, `undefined` if not found, or `null` if a
120 * Class was found.
121 */
122 getCmp: function(id) {
123 return Ext.ComponentManager.get(id);
124 },
125
126 /**
127 * Returns the current orientation of the mobile device
128 * @return {String} Either 'portrait' or 'landscape'
129 */
130 getOrientation: function() {
131 return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
132 },
133
134 /**
135 * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
136 * DOM (if applicable) and calling their destroy functions (if available). This method is primarily
137 * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
138 * {@link Ext.util.Observable} can be passed in. Any number of elements and/or components can be
139 * passed into this function in a single call as separate arguments.
140 *
141 * @param {Ext.Element/Ext.Component/Ext.Element[]/Ext.Component[]...} args
142 * An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
143 */
144 destroy: function() {
145 var ln = arguments.length,
146 i, arg;
147
148 for (i = 0; i < ln; i++) {
149 arg = arguments[i];
150 if (arg) {
151 if (Ext.isArray(arg)) {
152 this.destroy.apply(this, arg);
153 }
154 else if (Ext.isFunction(arg.destroy)) {
155 arg.destroy();
156 }
157 else if (arg.dom) {
158 arg.remove();
159 }
160 }
161 }
162 },
163
164 /**
165 * Execute a callback function in a particular scope. If no function is passed the call is ignored.
166 *
167 * For example, these lines are equivalent:
168 *
169 * Ext.callback(myFunc, this, [arg1, arg2]);
170 * Ext.isFunction(myFunc) && myFunc.apply(this, [arg1, arg2]);
171 *
172 * @param {Function} callback The callback to execute
173 * @param {Object} [scope] The scope to execute in
174 * @param {Array} [args] The arguments to pass to the function
175 * @param {Number} [delay] Pass a number to delay the call by a number of milliseconds.
176 */
177 callback: function(callback, scope, args, delay){
178 if(Ext.isFunction(callback)){
179 args = args || [];
180 scope = scope || window;
181 if (delay) {
182 Ext.defer(callback, delay, scope, args);
183 } else {
184 callback.apply(scope, args);
185 }
186 }
187 },
188
189 /**
190 * Alias for {@link Ext.String#htmlEncode}.
191 * @inheritdoc Ext.String#htmlEncode
192 */
193 htmlEncode : function(value) {
194 return Ext.String.htmlEncode(value);
195 },
196
197 /**
198 * Alias for {@link Ext.String#htmlDecode}.
199 * @inheritdoc Ext.String#htmlDecode
200 */
201 htmlDecode : function(value) {
202 return Ext.String.htmlDecode(value);
203 },
204
205 /**
206 * Alias for {@link Ext.String#urlAppend}.
207 * @inheritdoc Ext.String#urlAppend
208 */
209 urlAppend : function(url, s) {
210 return Ext.String.urlAppend(url, s);
211 }
212});
213
214
215Ext.ns = Ext.namespace;
216
217// for old browsers
218window.undefined = window.undefined;
219
220/**
221 * @class Ext
222 */
223(function(){
224/*
225FF 3.6 - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17
226FF 4.0.1 - Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
227FF 5.0 - Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0
228
229IE6 - Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)
230IE7 - Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1;)
231IE8 - Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
232IE9 - Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)
233
234Chrome 11 - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.60 Safari/534.24
235
236Safari 5 - Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
237
238Opera 11.11 - Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11
239*/
240 var check = function(regex){
241 return regex.test(Ext.userAgent);
242 },
243 isStrict = document.compatMode == "CSS1Compat",
244 version = function (is, regex) {
245 var m;
246 return (is && (m = regex.exec(Ext.userAgent))) ? parseFloat(m[1]) : 0;
247 },
248 docMode = document.documentMode,
249 isOpera = check(/opera/),
250 isOpera10_5 = isOpera && check(/version\/10\.5/),
251 isChrome = check(/\bchrome\b/),
252 isWebKit = check(/webkit/),
253 isSafari = !isChrome && check(/safari/),
254 isSafari2 = isSafari && check(/applewebkit\/4/), // unique to Safari 2
255 isSafari3 = isSafari && check(/version\/3/),
256 isSafari4 = isSafari && check(/version\/4/),
257 isSafari5 = isSafari && check(/version\/5/),
258 isIE = !isOpera && check(/msie/),
259 isIE7 = isIE && ((check(/msie 7/) && docMode != 8 && docMode != 9) || docMode == 7),
260 isIE8 = isIE && ((check(/msie 8/) && docMode != 7 && docMode != 9) || docMode == 8),
261 isIE9 = isIE && ((check(/msie 9/) && docMode != 7 && docMode != 8) || docMode == 9),
262 isIE6 = isIE && check(/msie 6/),
263 isGecko = !isWebKit && check(/gecko/),
264 isGecko3 = isGecko && check(/rv:1\.9/),
265 isGecko4 = isGecko && check(/rv:2\.0/),
266 isGecko5 = isGecko && check(/rv:5\./),
267 isGecko10 = isGecko && check(/rv:10\./),
268 isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
269 isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
270 isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
271 isWindows = check(/windows|win32/),
272 isMac = check(/macintosh|mac os x/),
273 isLinux = check(/linux/),
274 scrollbarSize = null,
275 chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
276 firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
277 ieVersion = version(isIE, /msie (\d+\.\d+)/),
278 operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
279 safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
280 webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
281 isSecure = /^https/i.test(window.location.protocol);
282
283 // remove css image flicker
284 try {
285 document.execCommand("BackgroundImageCache", false, true);
286 } catch(e) {}
287
288
289 //<debug>
290 var primitiveRe = /string|number|boolean/;
291 function dumpObject (object) {
292 var member, type, value, name,
293 members = [];
294
295 // Cannot use Ext.encode since it can recurse endlessly (if we're lucky)
296 // ...and the data could be prettier!
297 for (name in object) {
298 if (object.hasOwnProperty(name)) {
299 value = object[name];
300
301 type = typeof value;
302 if (type == "function") {
303 continue;
304 }
305
306 if (type == 'undefined') {
307 member = type;
308 } else if (value === null || primitiveRe.test(type) || Ext.isDate(value)) {
309 member = Ext.encode(value);
310 } else if (Ext.isArray(value)) {
311 member = '[ ]';
312 } else if (Ext.isObject(value)) {
313 member = '{ }';
314 } else {
315 member = type;
316 }
317 members.push(Ext.encode(name) + ': ' + member);
318 }
319 }
320
321 if (members.length) {
322 return ' \nData: {\n ' + members.join(',\n ') + '\n}';
323 }
324 return '';
325 }
326
327 function log (message) {
328 var options, dump,
329 con = Ext.global.console,
330 level = 'log',
331 indent = log.indent || 0,
332 stack;
333
334 log.indent = indent;
335
336 if (typeof message != 'string') {
337 options = message;
338 message = options.msg || '';
339 level = options.level || level;
340 dump = options.dump;
341 stack = options.stack;
342
343 if (options.indent) {
344 ++log.indent;
345 } else if (options.outdent) {
346 log.indent = indent = Math.max(indent - 1, 0);
347 }
348
349 if (dump && !(con && con.dir)) {
350 message += dumpObject(dump);
351 dump = null;
352 }
353 }
354
355 if (arguments.length > 1) {
356 message += Array.prototype.slice.call(arguments, 1).join('');
357 }
358
359 message = indent ? Ext.String.repeat(' ', log.indentSize * indent) + message : message;
360 // w/o console, all messages are equal, so munge the level into the message:
361 if (level != 'log') {
362 message = '[' + level.charAt(0).toUpperCase() + '] ' + message;
363 }
364
365 // Not obvious, but 'console' comes and goes when Firebug is turned on/off, so
366 // an early test may fail either direction if Firebug is toggled.
367 //
368 if (con) { // if (Firebug-like console)
369 if (con[level]) {
370 con[level](message);
371 } else {
372 con.log(message);
373 }
374
375 if (dump) {
376 con.dir(dump);
377 }
378
379 if (stack && con.trace) {
380 // Firebug's console.error() includes a trace already...
381 if (!con.firebug || level != 'error') {
382 con.trace();
383 }
384 }
385 } else {
386 if (Ext.isOpera) {
387 opera.postError(message);
388 } else {
389 var out = log.out,
390 max = log.max;
391
392 if (out.length >= max) {
393 // this formula allows out.max to change (via debugger), where the
394 // more obvious "max/4" would not quite be the same
395 Ext.Array.erase(out, 0, out.length - 3 * Math.floor(max / 4)); // keep newest 75%
396 }
397
398 out.push(message);
399 }
400 }
401
402 // Mostly informational, but the Ext.Error notifier uses them:
403 ++log.count;
404 ++log.counters[level];
405 }
406
407 function logx (level, args) {
408 if (typeof args[0] == 'string') {
409 args.unshift({});
410 }
411 args[0].level = level;
412 log.apply(this, args);
413 }
414
415 log.error = function () {
416 logx('error', Array.prototype.slice.call(arguments));
417 }
418 log.info = function () {
419 logx('info', Array.prototype.slice.call(arguments));
420 }
421 log.warn = function () {
422 logx('warn', Array.prototype.slice.call(arguments));
423 }
424
425 log.count = 0;
426 log.counters = { error: 0, warn: 0, info: 0, log: 0 };
427 log.indentSize = 2;
428 log.out = [];
429 log.max = 750;
430 log.show = function () {
431 window.open('','extlog').document.write([
432 '<html><head><script type="text/javascript">',
433 'var lastCount = 0;',
434 'function update () {',
435 'var ext = window.opener.Ext,',
436 'extlog = ext && ext.log;',
437 'if (extlog && extlog.out && lastCount != extlog.count) {',
438 'lastCount = extlog.count;',
439 'var s = "<tt>" + extlog.out.join("~~~").replace(/[&]/g, "&").replace(/[<]/g, "<").replace(/[ ]/g, " ").replace(/\\~\\~\\~/g, "<br>") + "</tt>";',
440 'document.body.innerHTML = s;',
441 '}',
442 'setTimeout(update, 1000);',
443 '}',
444 'setTimeout(update, 1000);',
445 '</script></head><body></body></html>'].join(''));
446 };
447 //</debug>
448
449 var nullLog = function () {};
450 nullLog.info = nullLog.warn = nullLog.error = Ext.emptyFn;
451
452 Ext.setVersion('extjs', '4.1.0');
453 Ext.apply(Ext, {
454 /**
455 * @property {String} SSL_SECURE_URL
456 * URL to a blank file used by Ext when in secure mode for iframe src and onReady src
457 * to prevent the IE insecure content warning (`'about:blank'`, except for IE
458 * in secure mode, which is `'javascript:""'`).
459 */
460 SSL_SECURE_URL : isSecure && isIE ? 'javascript:\'\'' : 'about:blank',
461
462 /**
463 * @property {Boolean} enableFx
464 * True if the {@link Ext.fx.Anim} Class is available.
465 */
466
467 /**
468 * @property {Boolean} scopeResetCSS
469 * True to scope the reset CSS to be just applied to Ext components. Note that this
470 * wraps root containers with an additional element. Also remember that when you turn
471 * on this option, you have to use ext-all-scoped (unless you use the bootstrap.js to
472 * load your javascript, in which case it will be handled for you).
473 */
474 scopeResetCSS : Ext.buildSettings.scopeResetCSS,
475
476 /**
477 * @property {String} resetCls
478 * The css class used to wrap Ext components when the {@link #scopeResetCSS} option
479 * is used.
480 */
481 resetCls: Ext.buildSettings.baseCSSPrefix + 'reset',
482
483 /**
484 * @property {Boolean} enableNestedListenerRemoval
485 * **Experimental.** True to cascade listener removal to child elements when an element
486 * is removed. Currently not optimized for performance.
487 */
488 enableNestedListenerRemoval : false,
489
490 /**
491 * @property {Boolean} USE_NATIVE_JSON
492 * Indicates whether to use native browser parsing for JSON methods.
493 * This option is ignored if the browser does not support native JSON methods.
494 *
495 * **Note:** Native JSON methods will not work with objects that have functions.
496 * Also, property names must be quoted, otherwise the data will not parse.
497 */
498 USE_NATIVE_JSON : false,
499
500 /**
501 * Returns the dom node for the passed String (id), dom node, or Ext.Element.
502 * Optional 'strict' flag is needed for IE since it can return 'name' and
503 * 'id' elements by using getElementById.
504 *
505 * Here are some examples:
506 *
507 * // gets dom node based on id
508 * var elDom = Ext.getDom('elId');
509 * // gets dom node based on the dom node
510 * var elDom1 = Ext.getDom(elDom);
511 *
512 * // If we don't know if we are working with an
513 * // Ext.Element or a dom node use Ext.getDom
514 * function(el){
515 * var dom = Ext.getDom(el);
516 * // do something with the dom node
517 * }
518 *
519 * **Note:** the dom node to be found actually needs to exist (be rendered, etc)
520 * when this method is called to be successful.
521 *
522 * @param {String/HTMLElement/Ext.Element} el
523 * @return HTMLElement
524 */
525 getDom : function(el, strict) {
526 if (!el || !document) {
527 return null;
528 }
529 if (el.dom) {
530 return el.dom;
531 } else {
532 if (typeof el == 'string') {
533 var e = Ext.getElementById(el);
534 // IE returns elements with the 'name' and 'id' attribute.
535 // we do a strict check to return the element with only the id attribute
536 if (e && isIE && strict) {
537 if (el == e.getAttribute('id')) {
538 return e;
539 } else {
540 return null;
541 }
542 }
543 return e;
544 } else {
545 return el;
546 }
547 }
548 },
549
550 /**
551 * Removes a DOM node from the document.
552 *
553 * Removes this element from the document, removes all DOM event listeners, and
554 * deletes the cache reference. All DOM event listeners are removed from this element.
555 * If {@link Ext#enableNestedListenerRemoval Ext.enableNestedListenerRemoval} is
556 * `true`, then DOM event listeners are also removed from all child nodes.
557 * The body node will be ignored if passed in.
558 *
559 * @param {HTMLElement} node The node to remove
560 * @method
561 */
562 removeNode : isIE6 || isIE7 ? function() {
563 var d;
564 return function(n){
565 if(n && n.tagName != 'BODY'){
566 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
567 d = d || document.createElement('div');
568 d.appendChild(n);
569 d.innerHTML = '';
570 delete Ext.cache[n.id];
571 }
572 };
573 }() : function(n) {
574 if (n && n.parentNode && n.tagName != 'BODY') {
575 (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
576 n.parentNode.removeChild(n);
577 delete Ext.cache[n.id];
578 }
579 },
580
581 isStrict: isStrict,
582
583 isIEQuirks: isIE && !isStrict,
584
585 /**
586 * True if the detected browser is Opera.
587 * @type Boolean
588 */
589 isOpera : isOpera,
590
591 /**
592 * True if the detected browser is Opera 10.5x.
593 * @type Boolean
594 */
595 isOpera10_5 : isOpera10_5,
596
597 /**
598 * True if the detected browser uses WebKit.
599 * @type Boolean
600 */
601 isWebKit : isWebKit,
602
603 /**
604 * True if the detected browser is Chrome.
605 * @type Boolean
606 */
607 isChrome : isChrome,
608
609 /**
610 * True if the detected browser is Safari.
611 * @type Boolean
612 */
613 isSafari : isSafari,
614
615 /**
616 * True if the detected browser is Safari 3.x.
617 * @type Boolean
618 */
619 isSafari3 : isSafari3,
620
621 /**
622 * True if the detected browser is Safari 4.x.
623 * @type Boolean
624 */
625 isSafari4 : isSafari4,
626
627 /**
628 * True if the detected browser is Safari 5.x.
629 * @type Boolean
630 */
631 isSafari5 : isSafari5,
632
633 /**
634 * True if the detected browser is Safari 2.x.
635 * @type Boolean
636 */
637 isSafari2 : isSafari2,
638
639 /**
640 * True if the detected browser is Internet Explorer.
641 * @type Boolean
642 */
643 isIE : isIE,
644
645 /**
646 * True if the detected browser is Internet Explorer 6.x.
647 * @type Boolean
648 */
649 isIE6 : isIE6,
650
651 /**
652 * True if the detected browser is Internet Explorer 7.x.
653 * @type Boolean
654 */
655 isIE7 : isIE7,
656
657 /**
658 * True if the detected browser is Internet Explorer 8.x.
659 * @type Boolean
660 */
661 isIE8 : isIE8,
662
663 /**
664 * True if the detected browser is Internet Explorer 9.x.
665 * @type Boolean
666 */
667 isIE9 : isIE9,
668
669 /**
670 * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
671 * @type Boolean
672 */
673 isGecko : isGecko,
674
675 /**
676 * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
677 * @type Boolean
678 */
679 isGecko3 : isGecko3,
680
681 /**
682 * True if the detected browser uses a Gecko 2.0+ layout engine (e.g. Firefox 4.x).
683 * @type Boolean
684 */
685 isGecko4 : isGecko4,
686
687 /**
688 * True if the detected browser uses a Gecko 5.0+ layout engine (e.g. Firefox 5.x).
689 * @type Boolean
690 */
691 isGecko5 : isGecko5,
692
693 /**
694 * True if the detected browser uses a Gecko 5.0+ layout engine (e.g. Firefox 5.x).
695 * @type Boolean
696 */
697 isGecko10 : isGecko10,
698
699 /**
700 * True if the detected browser uses FireFox 3.0
701 * @type Boolean
702 */
703 isFF3_0 : isFF3_0,
704
705 /**
706 * True if the detected browser uses FireFox 3.5
707 * @type Boolean
708 */
709 isFF3_5 : isFF3_5,
710
711 /**
712 * True if the detected browser uses FireFox 3.6
713 * @type Boolean
714 */
715 isFF3_6 : isFF3_6,
716
717 /**
718 * True if the detected browser uses FireFox 4
719 * @type Boolean
720 */
721 isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
722
723 /**
724 * True if the detected browser uses FireFox 5
725 * @type Boolean
726 */
727 isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
728
729 /**
730 * True if the detected browser uses FireFox 10
731 * @type Boolean
732 */
733 isFF10 : 10 <= firefoxVersion && firefoxVersion < 11,
734
735 /**
736 * True if the detected platform is Linux.
737 * @type Boolean
738 */
739 isLinux : isLinux,
740
741 /**
742 * True if the detected platform is Windows.
743 * @type Boolean
744 */
745 isWindows : isWindows,
746
747 /**
748 * True if the detected platform is Mac OS.
749 * @type Boolean
750 */
751 isMac : isMac,
752
753 /**
754 * The current version of Chrome (0 if the browser is not Chrome).
755 * @type Number
756 */
757 chromeVersion: chromeVersion,
758
759 /**
760 * The current version of Firefox (0 if the browser is not Firefox).
761 * @type Number
762 */
763 firefoxVersion: firefoxVersion,
764
765 /**
766 * The current version of IE (0 if the browser is not IE). This does not account
767 * for the documentMode of the current page, which is factored into {@link #isIE7},
768 * {@link #isIE8} and {@link #isIE9}. Thus this is not always true:
769 *
770 * Ext.isIE8 == (Ext.ieVersion == 8)
771 *
772 * @type Number
773 */
774 ieVersion: ieVersion,
775
776 /**
777 * The current version of Opera (0 if the browser is not Opera).
778 * @type Number
779 */
780 operaVersion: operaVersion,
781
782 /**
783 * The current version of Safari (0 if the browser is not Safari).
784 * @type Number
785 */
786 safariVersion: safariVersion,
787
788 /**
789 * The current version of WebKit (0 if the browser does not use WebKit).
790 * @type Number
791 */
792 webKitVersion: webKitVersion,
793
794 /**
795 * True if the page is running over SSL
796 * @type Boolean
797 */
798 isSecure: isSecure,
799
800 /**
801 * URL to a 1x1 transparent gif image used by Ext to create inline icons with
802 * CSS background images. In older versions of IE, this defaults to
803 * "http://sencha.com/s.gif" and you should change this to a URL on your server.
804 * For other browsers it uses an inline data URL.
805 * @type String
806 */
807 BLANK_IMAGE_URL : (isIE6 || isIE7) ? '/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
808
809 /**
810 * Utility method for returning a default value if the passed value is empty.
811 *
812 * The value is deemed to be empty if it is:
813 *
814 * - null
815 * - undefined
816 * - an empty array
817 * - a zero length string (Unless the `allowBlank` parameter is `true`)
818 *
819 * @param {Object} value The value to test
820 * @param {Object} defaultValue The value to return if the original value is empty
821 * @param {Boolean} [allowBlank=false] true to allow zero length strings to qualify as non-empty.
822 * @return {Object} value, if non-empty, else defaultValue
823 * @deprecated 4.0.0 Use {@link Ext#valueFrom} instead
824 */
825 value : function(v, defaultValue, allowBlank){
826 return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
827 },
828
829 /**
830 * Escapes the passed string for use in a regular expression.
831 * @param {String} str
832 * @return {String}
833 * @deprecated 4.0.0 Use {@link Ext.String#escapeRegex} instead
834 */
835 escapeRe : function(s) {
836 return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
837 },
838
839 /**
840 * Applies event listeners to elements by selectors when the document is ready.
841 * The event name is specified with an `@` suffix.
842 *
843 * Ext.addBehaviors({
844 * // add a listener for click on all anchors in element with id foo
845 * '#foo a@click' : function(e, t){
846 * // do something
847 * },
848 *
849 * // add the same listener to multiple selectors (separated by comma BEFORE the @)
850 * '#foo a, #bar span.some-class@mouseover' : function(){
851 * // do something
852 * }
853 * });
854 *
855 * @param {Object} obj The list of behaviors to apply
856 */
857 addBehaviors : function(o){
858 if(!Ext.isReady){
859 Ext.onReady(function(){
860 Ext.addBehaviors(o);
861 });
862 } else {
863 var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
864 parts,
865 b,
866 s;
867 for (b in o) {
868 if ((parts = b.split('@'))[1]) { // for Object prototype breakers
869 s = parts[0];
870 if(!cache[s]){
871 cache[s] = Ext.select(s);
872 }
873 cache[s].on(parts[1], o[b]);
874 }
875 }
876 cache = null;
877 }
878 },
879
880 /**
881 * Returns the size of the browser scrollbars. This can differ depending on
882 * operating system settings, such as the theme or font size.
883 * @param {Boolean} [force] true to force a recalculation of the value.
884 * @return {Object} An object containing scrollbar sizes.
885 * @return.width {Number} The width of the vertical scrollbar.
886 * @return.height {Number} The height of the horizontal scrollbar.
887 */
888 getScrollbarSize: function (force) {
889 if (!Ext.isReady) {
890 return {};
891 }
892
893 if (force || !scrollbarSize) {
894 var db = document.body,
895 div = document.createElement('div');
896
897 div.style.width = div.style.height = '100px';
898 div.style.overflow = 'scroll';
899 div.style.position = 'absolute';
900
901 db.appendChild(div); // now we can measure the div...
902
903 // at least in iE9 the div is not 100px - the scrollbar size is removed!
904 scrollbarSize = {
905 width: div.offsetWidth - div.clientWidth,
906 height: div.offsetHeight - div.clientHeight
907 };
908
909 db.removeChild(div);
910 }
911
912 return scrollbarSize;
913 },
914
915 /**
916 * Utility method for getting the width of the browser's vertical scrollbar. This
917 * can differ depending on operating system settings, such as the theme or font size.
918 *
919 * This method is deprected in favor of {@link #getScrollbarSize}.
920 *
921 * @param {Boolean} [force] true to force a recalculation of the value.
922 * @return {Number} The width of a vertical scrollbar.
923 * @deprecated
924 */
925 getScrollBarWidth: function(force){
926 var size = Ext.getScrollbarSize(force);
927 return size.width + 2; // legacy fudge factor
928 },
929
930 /**
931 * Copies a set of named properties fom the source object to the destination object.
932 *
933 * Example:
934 *
935 * ImageComponent = Ext.extend(Ext.Component, {
936 * initComponent: function() {
937 * this.autoEl = { tag: 'img' };
938 * MyComponent.superclass.initComponent.apply(this, arguments);
939 * this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
940 * }
941 * });
942 *
943 * Important note: To borrow class prototype methods, use {@link Ext.Base#borrow} instead.
944 *
945 * @param {Object} dest The destination object.
946 * @param {Object} source The source object.
947 * @param {String/String[]} names Either an Array of property names, or a comma-delimited list
948 * of property names to copy.
949 * @param {Boolean} [usePrototypeKeys] Defaults to false. Pass true to copy keys off of the
950 * prototype as well as the instance.
951 * @return {Object} The modified object.
952 */
953 copyTo : function(dest, source, names, usePrototypeKeys){
954 if(typeof names == 'string'){
955 names = names.split(/[,;\s]/);
956 }
957
958 var n,
959 nLen = names.length,
960 name;
961
962 for(n = 0; n < nLen; n++) {
963 name = names[n];
964
965 if(usePrototypeKeys || source.hasOwnProperty(name)){
966 dest[name] = source[name];
967 }
968 }
969
970 return dest;
971 },
972
973 /**
974 * Attempts to destroy and then remove a set of named properties of the passed object.
975 * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
976 * @param {String...} args One or more names of the properties to destroy and remove from the object.
977 */
978 destroyMembers : function(o){
979 for (var i = 1, a = arguments, len = a.length; i < len; i++) {
980 Ext.destroy(o[a[i]]);
981 delete o[a[i]];
982 }
983 },
984
985 /**
986 * Logs a message. If a console is present it will be used. On Opera, the method
987 * "opera.postError" is called. In other cases, the message is logged to an array
988 * "Ext.log.out". An attached debugger can watch this array and view the log. The
989 * log buffer is limited to a maximum of "Ext.log.max" entries (defaults to 250).
990 * The `Ext.log.out` array can also be written to a popup window by entering the
991 * following in the URL bar (a "bookmarklet"):
992 *
993 * javascript:void(Ext.log.show());
994 *
995 * If additional parameters are passed, they are joined and appended to the message.
996 * A technique for tracing entry and exit of a function is this:
997 *
998 * function foo () {
999 * Ext.log({ indent: 1 }, '>> foo');
1000 *
1001 * // log statements in here or methods called from here will be indented
1002 * // by one step
1003 *
1004 * Ext.log({ outdent: 1 }, '<< foo');
1005 * }
1006 *
1007 * This method does nothing in a release build.
1008 *
1009 * @param {String/Object} message The message to log or an options object with any
1010 * of the following properties:
1011 *
1012 * - `msg`: The message to log (required).
1013 * - `level`: One of: "error", "warn", "info" or "log" (the default is "log").
1014 * - `dump`: An object to dump to the log as part of the message.
1015 * - `stack`: True to include a stack trace in the log.
1016 * - `indent`: Cause subsequent log statements to be indented one step.
1017 * - `outdent`: Cause this and following statements to be one step less indented.
1018 *
1019 * @method
1020 */
1021 log :
1022 //<debug>
1023 log ||
1024 //</debug>
1025 nullLog,
1026
1027 /**
1028 * Partitions the set into two sets: a true set and a false set.
1029 *
1030 * Example 1:
1031 *
1032 * Ext.partition([true, false, true, true, false]);
1033 * // returns [[true, true, true], [false, false]]
1034 *
1035 * Example 2:
1036 *
1037 * Ext.partition(
1038 * Ext.query("p"),
1039 * function(val){
1040 * return val.className == "class1"
1041 * }
1042 * );
1043 * // true are those paragraph elements with a className of "class1",
1044 * // false set are those that do not have that className.
1045 *
1046 * @param {Array/NodeList} arr The array to partition
1047 * @param {Function} truth (optional) a function to determine truth.
1048 * If this is omitted the element itself must be able to be evaluated for its truthfulness.
1049 * @return {Array} [array of truish values, array of falsy values]
1050 * @deprecated 4.0.0 Will be removed in the next major version
1051 */
1052 partition : function(arr, truth){
1053 var ret = [[],[]],
1054 a, v,
1055 aLen = arr.length;
1056
1057 for (a = 0; a < aLen; a++) {
1058 v = arr[a];
1059 ret[ (truth && truth(v, a, arr)) || (!truth && v) ? 0 : 1].push(v);
1060 }
1061
1062 return ret;
1063 },
1064
1065 /**
1066 * Invokes a method on each item in an Array.
1067 *
1068 * Example:
1069 *
1070 * Ext.invoke(Ext.query("p"), "getAttribute", "id");
1071 * // [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
1072 *
1073 * @param {Array/NodeList} arr The Array of items to invoke the method on.
1074 * @param {String} methodName The method name to invoke.
1075 * @param {Object...} args Arguments to send into the method invocation.
1076 * @return {Array} The results of invoking the method on each item in the array.
1077 * @deprecated 4.0.0 Will be removed in the next major version
1078 */
1079 invoke : function(arr, methodName){
1080 var ret = [],
1081 args = Array.prototype.slice.call(arguments, 2),
1082 a, v,
1083 aLen = arr.length;
1084
1085 for (a = 0; a < aLen; a++) {
1086 v = arr[a];
1087
1088 if (v && typeof v[methodName] == 'function') {
1089 ret.push(v[methodName].apply(v, args));
1090 } else {
1091 ret.push(undefined);
1092 }
1093 }
1094
1095 return ret;
1096 },
1097
1098 /**
1099 * Zips N sets together.
1100 *
1101 * Example 1:
1102 *
1103 * Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
1104 *
1105 * Example 2:
1106 *
1107 * Ext.zip(
1108 * [ "+", "-", "+"],
1109 * [ 12, 10, 22],
1110 * [ 43, 15, 96],
1111 * function(a, b, c){
1112 * return "$" + a + "" + b + "." + c
1113 * }
1114 * ); // ["$+12.43", "$-10.15", "$+22.96"]
1115 *
1116 * @param {Array/NodeList...} arr This argument may be repeated. Array(s)
1117 * to contribute values.
1118 * @param {Function} zipper (optional) The last item in the argument list.
1119 * This will drive how the items are zipped together.
1120 * @return {Array} The zipped set.
1121 * @deprecated 4.0.0 Will be removed in the next major version
1122 */
1123 zip : function(){
1124 var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
1125 arrs = parts[0],
1126 fn = parts[1][0],
1127 len = Ext.max(Ext.pluck(arrs, "length")),
1128 ret = [];
1129
1130 for (var i = 0; i < len; i++) {
1131 ret[i] = [];
1132 if(fn){
1133 ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
1134 }else{
1135 for (var j = 0, aLen = arrs.length; j < aLen; j++){
1136 ret[i].push( arrs[j][i] );
1137 }
1138 }
1139 }
1140 return ret;
1141 },
1142
1143 /**
1144 * Turns an array into a sentence, joined by a specified connector - e.g.:
1145 *
1146 * Ext.toSentence(['Adama', 'Tigh', 'Roslin']); //'Adama, Tigh and Roslin'
1147 * Ext.toSentence(['Adama', 'Tigh', 'Roslin'], 'or'); //'Adama, Tigh or Roslin'
1148 *
1149 * @param {String[]} items The array to create a sentence from
1150 * @param {String} connector The string to use to connect the last two words.
1151 * Usually 'and' or 'or' - defaults to 'and'.
1152 * @return {String} The sentence string
1153 * @deprecated 4.0.0 Will be removed in the next major version
1154 */
1155 toSentence: function(items, connector) {
1156 var length = items.length;
1157
1158 if (length <= 1) {
1159 return items[0];
1160 } else {
1161 var head = items.slice(0, length - 1),
1162 tail = items[length - 1];
1163
1164 return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
1165 }
1166 },
1167
1168 /**
1169 * @property {Boolean} useShims
1170 * By default, Ext intelligently decides whether floating elements should be shimmed.
1171 * If you are using flash, you may want to set this to true.
1172 */
1173 useShims: isIE6
1174 });
1175})();
1176
1177/**
1178 * Loads Ext.app.Application class and starts it up with given configuration after the page is ready.
1179 *
1180 * See Ext.app.Application for details.
1181 *
1182 * @param {Object} config
1183 */
1184Ext.application = function(config) {
1185 Ext.require('Ext.app.Application');
1186
1187 Ext.onReady(function() {
1188 new Ext.app.Application(config);
1189 });
1190};