]> git.proxmox.com Git - extjs.git/blame - extjs/build/ext-debug.js
add extjs 6.0.1 sources
[extjs.git] / extjs / build / ext-debug.js
CommitLineData
6527f429
DM
1/*\r
2This file is part of Ext JS 6.0.1.250\r
3\r
4Copyright (c) 2011-2015 Sencha Inc\r
5\r
6Contact: http://www.sencha.com/contact\r
7\r
8GNU General Public License Usage\r
9This file may be used under the terms of the GNU General Public License version 3.0 as\r
10published by the Free Software Foundation and appearing in the file LICENSE included in the\r
11packaging of this file.\r
12\r
13Please review the following information to ensure the GNU General Public License version 3.0\r
14requirements will be met: http://www.gnu.org/copyleft/gpl.html.\r
15\r
16If you are unsure which license is appropriate for your use, please contact the sales department\r
17at http://www.sencha.com/contact.\r
18\r
19Version: 6.0.1.250 Build date: 2015-09-02 17:27:43 (22ef9ff0ebf584ff525541be37e753a703cc044b)\r
20\r
21*/\r
22
23var Ext = Ext || {};
24(function(manifest){
25 if(!Ext.manifest) {
26 Ext.manifest = manifest;
27 } else {
28 for(var name in manifest) {
29 Ext.manifest[name] = manifest[name];
30 }
31 }
32})({
33 "paths": {
34 "Ext": "../classic/classic/src",
35 "Ext.AbstractManager": "../packages/core/src/AbstractManager.js",
36 "Ext.Ajax": "../packages/core/src/Ajax.js",
37 "Ext.AnimationQueue": "../packages/core/src/AnimationQueue.js",
38 "Ext.ComponentManager": "../packages/core/src/ComponentManager.js",
39 "Ext.ComponentQuery": "../packages/core/src/ComponentQuery.js",
40 "Ext.Deferred": "../packages/core/src/Deferred.js",
41 "Ext.Evented": "../packages/core/src/Evented.js",
42 "Ext.Factory": "../packages/core/src/mixin/Factoryable.js",
43 "Ext.GlobalEvents": "../packages/core/src/GlobalEvents.js",
44 "Ext.JSON": "../packages/core/src/JSON.js",
45 "Ext.Mixin": "../packages/core/src/class/Mixin.js",
46 "Ext.Msg": "../classic/classic/src/window/MessageBox.js",
47 "Ext.Progress": "../packages/core/src/Progress.js",
48 "Ext.ProgressBase": "../packages/core/src/ProgressBase.js",
49 "Ext.Promise": "../packages/core/src/Promise.js",
50 "Ext.String.format": "../packages/core/src/Template.js",
51 "Ext.TaskQueue": "../packages/core/src/TaskQueue.js",
52 "Ext.Template": "../packages/core/src/Template.js",
53 "Ext.Widget": "../packages/core/src/Widget.js",
54 "Ext.XTemplate": "../packages/core/src/XTemplate.js",
55 "Ext.app": "../packages/core/src/app",
56 "Ext.data": "../packages/core/src/data",
57 "Ext.direct": "../packages/core/src/direct",
58 "Ext.dom": "../packages/core/src/dom",
59 "Ext.dom.ButtonElement": "../classic/classic/src/dom/ButtonElement.js",
60 "Ext.dom.Layer": "../classic/classic/src/dom/Layer.js",
61 "Ext.event": "../packages/core/src/event",
62 "Ext.event.publisher.MouseEnterLeave": "../classic/classic/src/event/publisher/MouseEnterLeave.js",
63 "Ext.fx.Animation": "../packages/core/src/fx/Animation.js",
64 "Ext.fx.Runner": "../packages/core/src/fx/Runner.js",
65 "Ext.fx.State": "../packages/core/src/fx/State.js",
66 "Ext.fx.animation": "../packages/core/src/fx/animation",
67 "Ext.fx.easing": "../packages/core/src/fx/easing",
68 "Ext.fx.layout": "../packages/core/src/fx/layout",
69 "Ext.fx.runner": "../packages/core/src/fx/runner",
70 "Ext.list": "../packages/core/src/list",
71 "Ext.mixin": "../packages/core/src/mixin",
72 "Ext.perf": "../packages/core/src/perf",
73 "Ext.plugin.Abstract": "../packages/core/src/plugin/Abstract.js",
74 "Ext.plugin.LazyItems": "../packages/core/src/plugin/LazyItems.js",
75 "Ext.promise": "../packages/core/src/promise",
76 "Ext.scroll": "../packages/core/src/scroll",
77 "Ext.util": "../packages/core/src/util",
78 "Ext.util.Animate": "../classic/classic/src/util/Animate.js",
79 "Ext.util.CSS": "../classic/classic/src/util/CSS.js",
80 "Ext.util.ClickRepeater": "../classic/classic/src/util/ClickRepeater.js",
81 "Ext.util.ComponentDragger": "../classic/classic/src/util/ComponentDragger.js",
82 "Ext.util.Cookies": "../classic/classic/src/util/Cookies.js",
83 "Ext.util.ElementContainer": "../classic/classic/src/util/ElementContainer.js",
84 "Ext.util.Floating": "../classic/classic/src/util/Floating.js",
85 "Ext.util.FocusTrap": "../classic/classic/src/util/FocusTrap.js",
86 "Ext.util.Focusable": "../classic/classic/src/util/Focusable.js",
87 "Ext.util.FocusableContainer": "../classic/classic/src/util/FocusableContainer.js",
88 "Ext.util.Format.format": "../packages/core/src/Template.js",
89 "Ext.util.KeyMap": "../classic/classic/src/util/KeyMap.js",
90 "Ext.util.KeyNav": "../classic/classic/src/util/KeyNav.js",
91 "Ext.util.KeyboardInteractive": "../classic/classic/src/util/KeyboardInteractive.js",
92 "Ext.util.Memento": "../classic/classic/src/util/Memento.js",
93 "Ext.util.ProtoElement": "../classic/classic/src/util/ProtoElement.js",
94 "Ext.util.Queue": "../classic/classic/src/util/Queue.js",
95 "Ext.util.Renderable": "../classic/classic/src/util/Renderable.js",
96 "Ext.util.StoreHolder": "../classic/classic/src/util/StoreHolder.js"
97 },
98 "loadOrder": [
99 {
100 "path": "../packages/core/src/class/Mixin.js",
101 "requires": [],
102 "uses": [],
103 "idx": 0
104 },
105 {
106 "path": "../packages/core/src/util/DelayedTask.js",
107 "requires": [],
108 "uses": [
109 76
110 ],
111 "idx": 1
112 },
113 {
114 "path": "../packages/core/src/util/Event.js",
115 "requires": [
116 1
117 ],
118 "uses": [],
119 "idx": 2
120 },
121 {
122 "path": "../packages/core/src/mixin/Identifiable.js",
123 "requires": [],
124 "uses": [],
125 "idx": 3
126 },
127 {
128 "path": "../packages/core/src/mixin/Observable.js",
129 "requires": [
130 0,
131 2,
132 3
133 ],
134 "uses": [
135 51
136 ],
137 "idx": 4
138 },
139 {
140 "path": "../packages/core/src/util/HashMap.js",
141 "requires": [
142 4
143 ],
144 "uses": [],
145 "idx": 5
146 },
147 {
148 "path": "../packages/core/src/AbstractManager.js",
149 "requires": [
150 5
151 ],
152 "uses": [],
153 "idx": 6
154 },
155 {
156 "path": "../packages/core/src/promise/Consequence.js",
157 "requires": [],
158 "uses": [
159 8
160 ],
161 "idx": 7
162 },
163 {
164 "path": "../packages/core/src/promise/Deferred.js",
165 "requires": [
166 7
167 ],
168 "uses": [
169 9
170 ],
171 "idx": 8
172 },
173 {
174 "path": "../packages/core/src/promise/Promise.js",
175 "requires": [
176 8
177 ],
178 "uses": [],
179 "idx": 9
180 },
181 {
182 "path": "../packages/core/src/Promise.js",
183 "requires": [
184 9
185 ],
186 "uses": [
187 8
188 ],
189 "idx": 10
190 },
191 {
192 "path": "../packages/core/src/Deferred.js",
193 "requires": [
194 8,
195 10
196 ],
197 "uses": [
198 9
199 ],
200 "idx": 11
201 },
202 {
203 "path": "../packages/core/src/mixin/Factoryable.js",
204 "requires": [],
205 "uses": [],
206 "idx": 12
207 },
208 {
209 "path": "../packages/core/src/data/request/Base.js",
210 "requires": [
211 11,
212 12
213 ],
214 "uses": [
215 17
216 ],
217 "idx": 13
218 },
219 {
220 "path": "../packages/core/src/data/flash/BinaryXhr.js",
221 "requires": [],
222 "uses": [
223 76
224 ],
225 "idx": 14
226 },
227 {
228 "path": "../packages/core/src/data/request/Ajax.js",
229 "requires": [
230 13,
231 14
232 ],
233 "uses": [
234 76
235 ],
236 "idx": 15
237 },
238 {
239 "path": "../packages/core/src/data/request/Form.js",
240 "requires": [
241 13
242 ],
243 "uses": [],
244 "idx": 16
245 },
246 {
247 "path": "../packages/core/src/data/Connection.js",
248 "requires": [
249 4,
250 11,
251 14,
252 15,
253 16
254 ],
255 "uses": [
256 12,
257 49
258 ],
259 "idx": 17
260 },
261 {
262 "path": "../packages/core/src/Ajax.js",
263 "requires": [
264 17
265 ],
266 "uses": [],
267 "idx": 18
268 },
269 {
270 "path": "../packages/core/src/AnimationQueue.js",
271 "requires": [],
272 "uses": [],
273 "idx": 19
274 },
275 {
276 "path": "../packages/core/src/ComponentManager.js",
277 "requires": [],
278 "uses": [
279 23,
280 49
281 ],
282 "idx": 20
283 },
284 {
285 "path": "../packages/core/src/util/Operators.js",
286 "requires": [],
287 "uses": [],
288 "idx": 21
289 },
290 {
291 "path": "../packages/core/src/util/LruCache.js",
292 "requires": [
293 5
294 ],
295 "uses": [],
296 "idx": 22
297 },
298 {
299 "path": "../packages/core/src/ComponentQuery.js",
300 "requires": [
301 20,
302 21,
303 22
304 ],
305 "uses": [
306 85
307 ],
308 "idx": 23
309 },
310 {
311 "path": "../packages/core/src/Evented.js",
312 "requires": [
313 4
314 ],
315 "uses": [],
316 "idx": 24
317 },
318 {
319 "path": "../packages/core/src/util/Positionable.js",
320 "requires": [],
321 "uses": [
322 33,
323 49
324 ],
325 "idx": 25
326 },
327 {
328 "path": "../packages/core/src/dom/UnderlayPool.js",
329 "requires": [],
330 "uses": [
331 49
332 ],
333 "idx": 26
334 },
335 {
336 "path": "../packages/core/src/dom/Underlay.js",
337 "requires": [
338 26
339 ],
340 "uses": [],
341 "idx": 27
342 },
343 {
344 "path": "../packages/core/src/dom/Shadow.js",
345 "requires": [
346 27
347 ],
348 "uses": [],
349 "idx": 28
350 },
351 {
352 "path": "../packages/core/src/dom/Shim.js",
353 "requires": [
354 27
355 ],
356 "uses": [],
357 "idx": 29
358 },
359 {
360 "path": "../packages/core/src/dom/ElementEvent.js",
361 "requires": [
362 2
363 ],
364 "uses": [
365 36
366 ],
367 "idx": 30
368 },
369 {
370 "path": "../packages/core/src/event/publisher/Publisher.js",
371 "requires": [],
372 "uses": [],
373 "idx": 31
374 },
375 {
376 "path": "../packages/core/src/util/Offset.js",
377 "requires": [],
378 "uses": [],
379 "idx": 32
380 },
381 {
382 "path": "../packages/core/src/util/Region.js",
383 "requires": [
384 32
385 ],
386 "uses": [],
387 "idx": 33
388 },
389 {
390 "path": "../packages/core/src/util/Point.js",
391 "requires": [
392 33
393 ],
394 "uses": [],
395 "idx": 34
396 },
397 {
398 "path": "../packages/core/src/event/Event.js",
399 "requires": [
400 34
401 ],
402 "uses": [],
403 "idx": 35
404 },
405 {
406 "path": "../packages/core/src/event/publisher/Dom.js",
407 "requires": [
408 31,
409 35
410 ],
411 "uses": [
412 76
413 ],
414 "idx": 36
415 },
416 {
417 "path": "../packages/core/src/event/publisher/Gesture.js",
418 "requires": [
419 19,
420 34,
421 36
422 ],
423 "uses": [
424 35,
425 49,
426 258,
427 259,
428 260,
429 261,
430 262,
431 263,
432 264,
433 265,
434 266,
435 267,
436 268,
437 269
438 ],
439 "idx": 37
440 },
441 {
442 "path": "../packages/core/src/mixin/Templatable.js",
443 "requires": [
444 0
445 ],
446 "uses": [
447 49
448 ],
449 "idx": 38
450 },
451 {
452 "path": "../packages/core/src/TaskQueue.js",
453 "requires": [
454 19
455 ],
456 "uses": [],
457 "idx": 39
458 },
459 {
460 "path": "../packages/core/src/util/sizemonitor/Abstract.js",
461 "requires": [
462 38,
463 39
464 ],
465 "uses": [],
466 "idx": 40
467 },
468 {
469 "path": "../packages/core/src/util/sizemonitor/Scroll.js",
470 "requires": [
471 40
472 ],
473 "uses": [
474 39
475 ],
476 "idx": 41
477 },
478 {
479 "path": "../packages/core/src/util/sizemonitor/OverflowChange.js",
480 "requires": [
481 40
482 ],
483 "uses": [
484 39
485 ],
486 "idx": 42
487 },
488 {
489 "path": "../packages/core/src/util/SizeMonitor.js",
490 "requires": [
491 41,
492 42
493 ],
494 "uses": [],
495 "idx": 43
496 },
497 {
498 "path": "../packages/core/src/event/publisher/ElementSize.js",
499 "requires": [
500 31,
501 43
502 ],
503 "uses": [
504 39
505 ],
506 "idx": 44
507 },
508 {
509 "path": "../packages/core/src/util/paintmonitor/Abstract.js",
510 "requires": [],
511 "uses": [
512 49
513 ],
514 "idx": 45
515 },
516 {
517 "path": "../packages/core/src/util/paintmonitor/CssAnimation.js",
518 "requires": [
519 45
520 ],
521 "uses": [],
522 "idx": 46
523 },
524 {
525 "path": "../packages/core/src/util/PaintMonitor.js",
526 "requires": [
527 46
528 ],
529 "uses": [],
530 "idx": 47
531 },
532 {
533 "path": "../packages/core/src/event/publisher/ElementPaint.js",
534 "requires": [
535 31,
536 39,
537 47
538 ],
539 "uses": [],
540 "idx": 48
541 },
542 {
543 "path": "../packages/core/src/dom/Element.js",
544 "requires": [
545 4,
546 25,
547 28,
548 29,
549 30,
550 36,
551 37,
552 44,
553 48
554 ],
555 "uses": [
556 31,
557 33,
558 74,
559 75,
560 76,
561 85,
562 92,
563 230,
564 270,
565 280,
566 282
567 ],
568 "idx": 49
569 },
570 {
571 "path": "../packages/core/src/util/Filter.js",
572 "requires": [],
573 "uses": [],
574 "idx": 50
575 },
576 {
577 "path": "../packages/core/src/util/Observable.js",
578 "requires": [
579 4
580 ],
581 "uses": [],
582 "idx": 51
583 },
584 {
585 "path": "../packages/core/src/util/AbstractMixedCollection.js",
586 "requires": [
587 50,
588 51
589 ],
590 "uses": [],
591 "idx": 52
592 },
593 {
594 "path": "../packages/core/src/util/Sorter.js",
595 "requires": [],
596 "uses": [],
597 "idx": 53
598 },
599 {
600 "path": "../packages/core/src/util/Sortable.js",
601 "requires": [
602 53
603 ],
604 "uses": [
605 55
606 ],
607 "idx": 54
608 },
609 {
610 "path": "../packages/core/src/util/MixedCollection.js",
611 "requires": [
612 52,
613 54
614 ],
615 "uses": [],
616 "idx": 55
617 },
618 {
619 "path": "../packages/core/src/util/TaskRunner.js",
620 "requires": [],
621 "uses": [
622 76
623 ],
624 "idx": 56
625 },
626 {
627 "path": "../classic/classic/src/fx/target/Target.js",
628 "requires": [],
629 "uses": [],
630 "idx": 57
631 },
632 {
633 "path": "../classic/classic/src/fx/target/Element.js",
634 "requires": [
635 57
636 ],
637 "uses": [],
638 "idx": 58
639 },
640 {
641 "path": "../classic/classic/src/fx/target/ElementCSS.js",
642 "requires": [
643 58
644 ],
645 "uses": [],
646 "idx": 59
647 },
648 {
649 "path": "../classic/classic/src/fx/target/CompositeElement.js",
650 "requires": [
651 58
652 ],
653 "uses": [],
654 "idx": 60
655 },
656 {
657 "path": "../classic/classic/src/fx/target/CompositeElementCSS.js",
658 "requires": [
659 59,
660 60
661 ],
662 "uses": [],
663 "idx": 61
664 },
665 {
666 "path": "../classic/classic/src/fx/target/Sprite.js",
667 "requires": [
668 57
669 ],
670 "uses": [],
671 "idx": 62
672 },
673 {
674 "path": "../classic/classic/src/fx/target/CompositeSprite.js",
675 "requires": [
676 62
677 ],
678 "uses": [],
679 "idx": 63
680 },
681 {
682 "path": "../classic/classic/src/fx/target/Component.js",
683 "requires": [
684 57
685 ],
686 "uses": [
687 76
688 ],
689 "idx": 64
690 },
691 {
692 "path": "../classic/classic/src/fx/Queue.js",
693 "requires": [
694 5
695 ],
696 "uses": [],
697 "idx": 65
698 },
699 {
700 "path": "../classic/classic/src/fx/Manager.js",
701 "requires": [
702 55,
703 56,
704 58,
705 59,
706 60,
707 61,
708 62,
709 63,
710 64,
711 65
712 ],
713 "uses": [],
714 "idx": 66
715 },
716 {
717 "path": "../classic/classic/src/fx/Animator.js",
718 "requires": [
719 51,
720 66
721 ],
722 "uses": [
723 72
724 ],
725 "idx": 67
726 },
727 {
728 "path": "../classic/classic/src/fx/CubicBezier.js",
729 "requires": [],
730 "uses": [],
731 "idx": 68
732 },
733 {
734 "path": "../classic/classic/src/fx/Easing.js",
735 "requires": [
736 68
737 ],
738 "uses": [],
739 "idx": 69
740 },
741 {
742 "path": "../classic/classic/src/fx/DrawPath.js",
743 "requires": [],
744 "uses": [],
745 "idx": 70
746 },
747 {
748 "path": "../classic/classic/src/fx/PropertyHandler.js",
749 "requires": [
750 70
751 ],
752 "uses": [],
753 "idx": 71
754 },
755 {
756 "path": "../classic/classic/src/fx/Anim.js",
757 "requires": [
758 51,
759 66,
760 67,
761 68,
762 69,
763 71
764 ],
765 "uses": [],
766 "idx": 72
767 },
768 {
769 "path": "../classic/classic/src/util/Animate.js",
770 "requires": [
771 66,
772 72
773 ],
774 "uses": [],
775 "idx": 73
776 },
777 {
778 "path": "../packages/core/src/dom/Fly.js",
779 "requires": [
780 49
781 ],
782 "uses": [],
783 "idx": 74
784 },
785 {
786 "path": "../packages/core/src/dom/CompositeElementLite.js",
787 "requires": [
788 74
789 ],
790 "uses": [
791 49
792 ],
793 "idx": 75
794 },
795 {
796 "path": "../packages/core/src/GlobalEvents.js",
797 "requires": [
798 4,
799 49
800 ],
801 "uses": [],
802 "idx": 76
803 },
804 {
805 "path": "../packages/core/src/JSON.js",
806 "requires": [],
807 "uses": [],
808 "idx": 77
809 },
810 {
811 "path": "../packages/core/src/mixin/Inheritable.js",
812 "requires": [
813 0
814 ],
815 "uses": [
816 20
817 ],
818 "idx": 78
819 },
820 {
821 "path": "../packages/core/src/mixin/Bindable.js",
822 "requires": [],
823 "uses": [
824 12
825 ],
826 "idx": 79
827 },
828 {
829 "path": "../packages/core/src/mixin/ComponentDelegation.js",
830 "requires": [
831 0,
832 4
833 ],
834 "uses": [
835 2
836 ],
837 "idx": 80
838 },
839 {
840 "path": "../packages/core/src/Widget.js",
841 "requires": [
842 24,
843 49,
844 78,
845 79,
846 80
847 ],
848 "uses": [
849 20,
850 23
851 ],
852 "idx": 81
853 },
854 {
855 "path": "../packages/core/src/ProgressBase.js",
856 "requires": [],
857 "uses": [
858 88
859 ],
860 "idx": 82
861 },
862 {
863 "path": "../packages/core/src/Progress.js",
864 "requires": [
865 81,
866 82
867 ],
868 "uses": [],
869 "idx": 83
870 },
871 {
872 "path": "../packages/core/src/util/Format.js",
873 "requires": [],
874 "uses": [
875 85,
876 230
877 ],
878 "idx": 84
879 },
880 {
881 "path": "../packages/core/src/Template.js",
882 "requires": [
883 84
884 ],
885 "uses": [
886 230
887 ],
888 "idx": 85
889 },
890 {
891 "path": "../packages/core/src/util/XTemplateParser.js",
892 "requires": [],
893 "uses": [],
894 "idx": 86
895 },
896 {
897 "path": "../packages/core/src/util/XTemplateCompiler.js",
898 "requires": [
899 86
900 ],
901 "uses": [],
902 "idx": 87
903 },
904 {
905 "path": "../packages/core/src/XTemplate.js",
906 "requires": [
907 85,
908 87
909 ],
910 "uses": [],
911 "idx": 88
912 },
913 {
914 "path": "../packages/core/src/app/EventDomain.js",
915 "requires": [
916 2
917 ],
918 "uses": [],
919 "idx": 89
920 },
921 {
922 "path": "../packages/core/src/app/domain/Component.js",
923 "requires": [
924 81,
925 89
926 ],
927 "uses": [],
928 "idx": 90
929 },
930 {
931 "path": "../classic/classic/src/util/ProtoElement.js",
932 "requires": [],
933 "uses": [
934 49,
935 230
936 ],
937 "idx": 91
938 },
939 {
940 "path": "../packages/core/src/dom/CompositeElement.js",
941 "requires": [
942 75
943 ],
944 "uses": [],
945 "idx": 92
946 },
947 {
948 "path": "../packages/core/src/scroll/Scroller.js",
949 "requires": [
950 12,
951 24
952 ],
953 "uses": [
954 76,
955 108,
956 109
957 ],
958 "idx": 93
959 },
960 {
961 "path": "../packages/core/src/fx/easing/Abstract.js",
962 "requires": [],
963 "uses": [],
964 "idx": 94
965 },
966 {
967 "path": "../packages/core/src/fx/easing/Momentum.js",
968 "requires": [
969 94
970 ],
971 "uses": [],
972 "idx": 95
973 },
974 {
975 "path": "../packages/core/src/fx/easing/Bounce.js",
976 "requires": [
977 94
978 ],
979 "uses": [],
980 "idx": 96
981 },
982 {
983 "path": "../packages/core/src/fx/easing/BoundMomentum.js",
984 "requires": [
985 94,
986 95,
987 96
988 ],
989 "uses": [],
990 "idx": 97
991 },
992 {
993 "path": "../packages/core/src/fx/easing/Linear.js",
994 "requires": [
995 94
996 ],
997 "uses": [],
998 "idx": 98
999 },
1000 {
1001 "path": "../packages/core/src/fx/easing/EaseOut.js",
1002 "requires": [
1003 98
1004 ],
1005 "uses": [],
1006 "idx": 99
1007 },
1008 {
1009 "path": "../packages/core/src/util/translatable/Abstract.js",
1010 "requires": [
1011 24,
1012 98
1013 ],
1014 "uses": [
1015 19
1016 ],
1017 "idx": 100
1018 },
1019 {
1020 "path": "../packages/core/src/util/translatable/Dom.js",
1021 "requires": [
1022 100
1023 ],
1024 "uses": [],
1025 "idx": 101
1026 },
1027 {
1028 "path": "../packages/core/src/util/translatable/CssTransform.js",
1029 "requires": [
1030 101
1031 ],
1032 "uses": [],
1033 "idx": 102
1034 },
1035 {
1036 "path": "../packages/core/src/util/translatable/ScrollPosition.js",
1037 "requires": [
1038 101
1039 ],
1040 "uses": [],
1041 "idx": 103
1042 },
1043 {
1044 "path": "../packages/core/src/util/translatable/ScrollParent.js",
1045 "requires": [
1046 101
1047 ],
1048 "uses": [],
1049 "idx": 104
1050 },
1051 {
1052 "path": "../packages/core/src/util/translatable/CssPosition.js",
1053 "requires": [
1054 101
1055 ],
1056 "uses": [],
1057 "idx": 105
1058 },
1059 {
1060 "path": "../packages/core/src/util/Translatable.js",
1061 "requires": [
1062 102,
1063 103,
1064 104,
1065 105
1066 ],
1067 "uses": [],
1068 "idx": 106
1069 },
1070 {
1071 "path": "../packages/core/src/scroll/Indicator.js",
1072 "requires": [
1073 81
1074 ],
1075 "uses": [],
1076 "idx": 107
1077 },
1078 {
1079 "path": "../packages/core/src/scroll/TouchScroller.js",
1080 "requires": [
1081 76,
1082 93,
1083 97,
1084 99,
1085 106,
1086 107
1087 ],
1088 "uses": [],
1089 "idx": 108
1090 },
1091 {
1092 "path": "../packages/core/src/scroll/DomScroller.js",
1093 "requires": [
1094 93
1095 ],
1096 "uses": [],
1097 "idx": 109
1098 },
1099 {
1100 "path": "../classic/classic/src/util/Floating.js",
1101 "requires": [],
1102 "uses": [
1103 20,
1104 76,
1105 333
1106 ],
1107 "idx": 110
1108 },
1109 {
1110 "path": "../classic/classic/src/util/ElementContainer.js",
1111 "requires": [],
1112 "uses": [],
1113 "idx": 111
1114 },
1115 {
1116 "path": "../classic/classic/src/util/Renderable.js",
1117 "requires": [
1118 49
1119 ],
1120 "uses": [
1121 88,
1122 119,
1123 230
1124 ],
1125 "idx": 112
1126 },
1127 {
1128 "path": "../classic/classic/src/state/Provider.js",
1129 "requires": [
1130 51
1131 ],
1132 "uses": [],
1133 "idx": 113
1134 },
1135 {
1136 "path": "../classic/classic/src/state/Manager.js",
1137 "requires": [
1138 113
1139 ],
1140 "uses": [],
1141 "idx": 114
1142 },
1143 {
1144 "path": "../classic/classic/src/state/Stateful.js",
1145 "requires": [
1146 56,
1147 114
1148 ],
1149 "uses": [],
1150 "idx": 115
1151 },
1152 {
1153 "path": "../classic/classic/src/util/Focusable.js",
1154 "requires": [
1155 1
1156 ],
1157 "uses": [
1158 23,
1159 35,
1160 49
1161 ],
1162 "idx": 116
1163 },
1164 {
1165 "path": "../packages/core/src/mixin/Accessible.js",
1166 "requires": [
1167 0
1168 ],
1169 "uses": [],
1170 "idx": 117
1171 },
1172 {
1173 "path": "../classic/classic/src/util/KeyboardInteractive.js",
1174 "requires": [
1175 0
1176 ],
1177 "uses": [
1178 35
1179 ],
1180 "idx": 118
1181 },
1182 {
1183 "path": "../classic/classic/src/Component.js",
1184 "requires": [
1185 20,
1186 23,
1187 25,
1188 51,
1189 73,
1190 76,
1191 78,
1192 79,
1193 80,
1194 91,
1195 92,
1196 93,
1197 108,
1198 109,
1199 110,
1200 111,
1201 112,
1202 115,
1203 116,
1204 117,
1205 118
1206 ],
1207 "uses": [
1208 1,
1209 49,
1210 66,
1211 88,
1212 195,
1213 230,
1214 328,
1215 329,
1216 330,
1217 333,
1218 340,
1219 342,
1220 411,
1221 554,
1222 568,
1223 572
1224 ],
1225 "idx": 119
1226 },
1227 {
1228 "path": "../classic/classic/src/layout/container/border/Region.js",
1229 "requires": [],
1230 "uses": [],
1231 "idx": 120
1232 },
1233 {
1234 "path": "../packages/core/src/app/EventBus.js",
1235 "requires": [
1236 90
1237 ],
1238 "uses": [
1239 89
1240 ],
1241 "idx": 121
1242 },
1243 {
1244 "path": "../packages/core/src/app/domain/Global.js",
1245 "requires": [
1246 76,
1247 89
1248 ],
1249 "uses": [],
1250 "idx": 122
1251 },
1252 {
1253 "path": "../packages/core/src/app/BaseController.js",
1254 "requires": [
1255 4,
1256 121,
1257 122
1258 ],
1259 "uses": [
1260 179,
1261 180,
1262 209
1263 ],
1264 "idx": 123
1265 },
1266 {
1267 "path": "../packages/core/src/app/Util.js",
1268 "requires": [],
1269 "uses": [],
1270 "idx": 124
1271 },
1272 {
1273 "path": "../packages/core/src/util/CollectionKey.js",
1274 "requires": [
1275 3
1276 ],
1277 "uses": [],
1278 "idx": 125
1279 },
1280 {
1281 "path": "../packages/core/src/util/Grouper.js",
1282 "requires": [
1283 53
1284 ],
1285 "uses": [],
1286 "idx": 126
1287 },
1288 {
1289 "path": "../packages/core/src/util/Collection.js",
1290 "requires": [
1291 4,
1292 50,
1293 53,
1294 125,
1295 126
1296 ],
1297 "uses": [
1298 169,
1299 170,
1300 171
1301 ],
1302 "idx": 127
1303 },
1304 {
1305 "path": "../packages/core/src/util/ObjectTemplate.js",
1306 "requires": [
1307 88
1308 ],
1309 "uses": [],
1310 "idx": 128
1311 },
1312 {
1313 "path": "../packages/core/src/data/schema/Role.js",
1314 "requires": [],
1315 "uses": [
1316 12
1317 ],
1318 "idx": 129
1319 },
1320 {
1321 "path": "../packages/core/src/data/schema/Association.js",
1322 "requires": [
1323 129
1324 ],
1325 "uses": [],
1326 "idx": 130
1327 },
1328 {
1329 "path": "../packages/core/src/data/schema/OneToOne.js",
1330 "requires": [
1331 130
1332 ],
1333 "uses": [],
1334 "idx": 131
1335 },
1336 {
1337 "path": "../packages/core/src/data/schema/ManyToOne.js",
1338 "requires": [
1339 130
1340 ],
1341 "uses": [],
1342 "idx": 132
1343 },
1344 {
1345 "path": "../packages/core/src/data/schema/ManyToMany.js",
1346 "requires": [
1347 130
1348 ],
1349 "uses": [],
1350 "idx": 133
1351 },
1352 {
1353 "path": "../packages/core/src/util/Inflector.js",
1354 "requires": [],
1355 "uses": [],
1356 "idx": 134
1357 },
1358 {
1359 "path": "../packages/core/src/data/schema/Namer.js",
1360 "requires": [
1361 12,
1362 134
1363 ],
1364 "uses": [],
1365 "idx": 135
1366 },
1367 {
1368 "path": "../packages/core/src/data/schema/Schema.js",
1369 "requires": [
1370 12,
1371 128,
1372 131,
1373 132,
1374 133,
1375 135
1376 ],
1377 "uses": [],
1378 "idx": 136
1379 },
1380 {
1381 "path": "../packages/core/src/data/AbstractStore.js",
1382 "requires": [
1383 4,
1384 12,
1385 50,
1386 127,
1387 136
1388 ],
1389 "uses": [
1390 175
1391 ],
1392 "idx": 137
1393 },
1394 {
1395 "path": "../packages/core/src/data/Error.js",
1396 "requires": [],
1397 "uses": [],
1398 "idx": 138
1399 },
1400 {
1401 "path": "../packages/core/src/data/ErrorCollection.js",
1402 "requires": [
1403 55,
1404 138
1405 ],
1406 "uses": [
1407 147
1408 ],
1409 "idx": 139
1410 },
1411 {
1412 "path": "../packages/core/src/data/operation/Operation.js",
1413 "requires": [],
1414 "uses": [],
1415 "idx": 140
1416 },
1417 {
1418 "path": "../packages/core/src/data/operation/Create.js",
1419 "requires": [
1420 140
1421 ],
1422 "uses": [],
1423 "idx": 141
1424 },
1425 {
1426 "path": "../packages/core/src/data/operation/Destroy.js",
1427 "requires": [
1428 140
1429 ],
1430 "uses": [],
1431 "idx": 142
1432 },
1433 {
1434 "path": "../packages/core/src/data/operation/Read.js",
1435 "requires": [
1436 140
1437 ],
1438 "uses": [],
1439 "idx": 143
1440 },
1441 {
1442 "path": "../packages/core/src/data/operation/Update.js",
1443 "requires": [
1444 140
1445 ],
1446 "uses": [],
1447 "idx": 144
1448 },
1449 {
1450 "path": "../packages/core/src/data/SortTypes.js",
1451 "requires": [],
1452 "uses": [],
1453 "idx": 145
1454 },
1455 {
1456 "path": "../packages/core/src/data/validator/Validator.js",
1457 "requires": [
1458 12
1459 ],
1460 "uses": [],
1461 "idx": 146
1462 },
1463 {
1464 "path": "../packages/core/src/data/field/Field.js",
1465 "requires": [
1466 12,
1467 145,
1468 146
1469 ],
1470 "uses": [],
1471 "idx": 147
1472 },
1473 {
1474 "path": "../packages/core/src/data/field/Boolean.js",
1475 "requires": [
1476 147
1477 ],
1478 "uses": [],
1479 "idx": 148
1480 },
1481 {
1482 "path": "../packages/core/src/data/field/Date.js",
1483 "requires": [
1484 147
1485 ],
1486 "uses": [],
1487 "idx": 149
1488 },
1489 {
1490 "path": "../packages/core/src/data/field/Integer.js",
1491 "requires": [
1492 147
1493 ],
1494 "uses": [],
1495 "idx": 150
1496 },
1497 {
1498 "path": "../packages/core/src/data/field/Number.js",
1499 "requires": [
1500 150
1501 ],
1502 "uses": [],
1503 "idx": 151
1504 },
1505 {
1506 "path": "../packages/core/src/data/field/String.js",
1507 "requires": [
1508 147
1509 ],
1510 "uses": [],
1511 "idx": 152
1512 },
1513 {
1514 "path": "../packages/core/src/data/identifier/Generator.js",
1515 "requires": [
1516 12
1517 ],
1518 "uses": [],
1519 "idx": 153
1520 },
1521 {
1522 "path": "../packages/core/src/data/identifier/Sequential.js",
1523 "requires": [
1524 153
1525 ],
1526 "uses": [],
1527 "idx": 154
1528 },
1529 {
1530 "path": "../packages/core/src/data/Model.js",
1531 "requires": [
1532 136,
1533 139,
1534 140,
1535 141,
1536 142,
1537 143,
1538 144,
1539 146,
1540 147,
1541 148,
1542 149,
1543 150,
1544 151,
1545 152,
1546 153,
1547 154
1548 ],
1549 "uses": [
1550 12,
1551 157,
1552 229
1553 ],
1554 "idx": 155
1555 },
1556 {
1557 "path": "../packages/core/src/data/ResultSet.js",
1558 "requires": [],
1559 "uses": [],
1560 "idx": 156
1561 },
1562 {
1563 "path": "../packages/core/src/data/reader/Reader.js",
1564 "requires": [
1565 4,
1566 12,
1567 22,
1568 88,
1569 156
1570 ],
1571 "uses": [
1572 136
1573 ],
1574 "idx": 157
1575 },
1576 {
1577 "path": "../packages/core/src/data/writer/Writer.js",
1578 "requires": [
1579 12
1580 ],
1581 "uses": [],
1582 "idx": 158
1583 },
1584 {
1585 "path": "../packages/core/src/data/proxy/Proxy.js",
1586 "requires": [
1587 4,
1588 12,
1589 136,
1590 157,
1591 158
1592 ],
1593 "uses": [
1594 140,
1595 141,
1596 142,
1597 143,
1598 144,
1599 155,
1600 188
1601 ],
1602 "idx": 159
1603 },
1604 {
1605 "path": "../packages/core/src/data/proxy/Client.js",
1606 "requires": [
1607 159
1608 ],
1609 "uses": [],
1610 "idx": 160
1611 },
1612 {
1613 "path": "../packages/core/src/data/proxy/Memory.js",
1614 "requires": [
1615 160
1616 ],
1617 "uses": [
1618 50,
1619 54
1620 ],
1621 "idx": 161
1622 },
1623 {
1624 "path": "../packages/core/src/data/ProxyStore.js",
1625 "requires": [
1626 137,
1627 140,
1628 141,
1629 142,
1630 143,
1631 144,
1632 155,
1633 159,
1634 161
1635 ],
1636 "uses": [
1637 136
1638 ],
1639 "idx": 162
1640 },
1641 {
1642 "path": "../packages/core/src/data/LocalStore.js",
1643 "requires": [
1644 0
1645 ],
1646 "uses": [
1647 127
1648 ],
1649 "idx": 163
1650 },
1651 {
1652 "path": "../packages/core/src/data/proxy/Server.js",
1653 "requires": [
1654 159
1655 ],
1656 "uses": [
1657 85,
1658 226
1659 ],
1660 "idx": 164
1661 },
1662 {
1663 "path": "../packages/core/src/data/proxy/Ajax.js",
1664 "requires": [
1665 18,
1666 164
1667 ],
1668 "uses": [],
1669 "idx": 165
1670 },
1671 {
1672 "path": "../packages/core/src/data/reader/Json.js",
1673 "requires": [
1674 77,
1675 157
1676 ],
1677 "uses": [],
1678 "idx": 166
1679 },
1680 {
1681 "path": "../packages/core/src/data/writer/Json.js",
1682 "requires": [
1683 158
1684 ],
1685 "uses": [],
1686 "idx": 167
1687 },
1688 {
1689 "path": "../packages/core/src/util/Group.js",
1690 "requires": [
1691 127
1692 ],
1693 "uses": [],
1694 "idx": 168
1695 },
1696 {
1697 "path": "../packages/core/src/util/SorterCollection.js",
1698 "requires": [
1699 53,
1700 127
1701 ],
1702 "uses": [],
1703 "idx": 169
1704 },
1705 {
1706 "path": "../packages/core/src/util/FilterCollection.js",
1707 "requires": [
1708 50,
1709 127
1710 ],
1711 "uses": [],
1712 "idx": 170
1713 },
1714 {
1715 "path": "../packages/core/src/util/GroupCollection.js",
1716 "requires": [
1717 127,
1718 168,
1719 169,
1720 170
1721 ],
1722 "uses": [],
1723 "idx": 171
1724 },
1725 {
1726 "path": "../packages/core/src/data/Store.js",
1727 "requires": [
1728 1,
1729 155,
1730 162,
1731 163,
1732 165,
1733 166,
1734 167,
1735 171
1736 ],
1737 "uses": [
1738 126,
1739 175,
1740 214
1741 ],
1742 "idx": 172
1743 },
1744 {
1745 "path": "../packages/core/src/data/reader/Array.js",
1746 "requires": [
1747 166
1748 ],
1749 "uses": [],
1750 "idx": 173
1751 },
1752 {
1753 "path": "../packages/core/src/data/ArrayStore.js",
1754 "requires": [
1755 161,
1756 172,
1757 173
1758 ],
1759 "uses": [],
1760 "idx": 174
1761 },
1762 {
1763 "path": "../packages/core/src/data/StoreManager.js",
1764 "requires": [
1765 55,
1766 174
1767 ],
1768 "uses": [
1769 12,
1770 161,
1771 167,
1772 172,
1773 173
1774 ],
1775 "idx": 175
1776 },
1777 {
1778 "path": "../packages/core/src/app/domain/Store.js",
1779 "requires": [
1780 89,
1781 137
1782 ],
1783 "uses": [],
1784 "idx": 176
1785 },
1786 {
1787 "path": "../packages/core/src/app/route/Queue.js",
1788 "requires": [],
1789 "uses": [
1790 55
1791 ],
1792 "idx": 177
1793 },
1794 {
1795 "path": "../packages/core/src/app/route/Route.js",
1796 "requires": [],
1797 "uses": [
1798 85
1799 ],
1800 "idx": 178
1801 },
1802 {
1803 "path": "../packages/core/src/util/History.js",
1804 "requires": [
1805 51
1806 ],
1807 "uses": [
1808 323
1809 ],
1810 "idx": 179
1811 },
1812 {
1813 "path": "../packages/core/src/app/route/Router.js",
1814 "requires": [
1815 177,
1816 178,
1817 179
1818 ],
1819 "uses": [],
1820 "idx": 180
1821 },
1822 {
1823 "path": "../packages/core/src/app/Controller.js",
1824 "requires": [
1825 20,
1826 90,
1827 123,
1828 124,
1829 175,
1830 176,
1831 180
1832 ],
1833 "uses": [
1834 23,
1835 136
1836 ],
1837 "idx": 181
1838 },
1839 {
1840 "path": "../packages/core/src/app/Application.js",
1841 "requires": [
1842 55,
1843 179,
1844 181
1845 ],
1846 "uses": [
1847 180
1848 ],
1849 "idx": 182
1850 },
1851 {
1852 "path": "../packages/core/src/app/Profile.js",
1853 "requires": [
1854 4
1855 ],
1856 "uses": [
1857 181
1858 ],
1859 "idx": 183
1860 },
1861 {
1862 "path": "../packages/core/src/app/domain/View.js",
1863 "requires": [
1864 89
1865 ],
1866 "uses": [],
1867 "idx": 184
1868 },
1869 {
1870 "path": "../packages/core/src/app/ViewController.js",
1871 "requires": [
1872 12,
1873 123,
1874 184
1875 ],
1876 "uses": [],
1877 "idx": 185
1878 },
1879 {
1880 "path": "../packages/core/src/util/Bag.js",
1881 "requires": [],
1882 "uses": [],
1883 "idx": 186
1884 },
1885 {
1886 "path": "../packages/core/src/util/Scheduler.js",
1887 "requires": [
1888 4,
1889 186
1890 ],
1891 "uses": [
1892 76
1893 ],
1894 "idx": 187
1895 },
1896 {
1897 "path": "../packages/core/src/data/Batch.js",
1898 "requires": [
1899 4
1900 ],
1901 "uses": [],
1902 "idx": 188
1903 },
1904 {
1905 "path": "../packages/core/src/data/matrix/Slice.js",
1906 "requires": [],
1907 "uses": [],
1908 "idx": 189
1909 },
1910 {
1911 "path": "../packages/core/src/data/matrix/Side.js",
1912 "requires": [
1913 189
1914 ],
1915 "uses": [],
1916 "idx": 190
1917 },
1918 {
1919 "path": "../packages/core/src/data/matrix/Matrix.js",
1920 "requires": [
1921 190
1922 ],
1923 "uses": [],
1924 "idx": 191
1925 },
1926 {
1927 "path": "../packages/core/src/data/session/ChangesVisitor.js",
1928 "requires": [],
1929 "uses": [],
1930 "idx": 192
1931 },
1932 {
1933 "path": "../packages/core/src/data/session/ChildChangesVisitor.js",
1934 "requires": [
1935 192
1936 ],
1937 "uses": [],
1938 "idx": 193
1939 },
1940 {
1941 "path": "../packages/core/src/data/session/BatchVisitor.js",
1942 "requires": [],
1943 "uses": [
1944 188
1945 ],
1946 "idx": 194
1947 },
1948 {
1949 "path": "../packages/core/src/data/Session.js",
1950 "requires": [
1951 136,
1952 188,
1953 191,
1954 192,
1955 193,
1956 194
1957 ],
1958 "uses": [],
1959 "idx": 195
1960 },
1961 {
1962 "path": "../packages/core/src/util/Schedulable.js",
1963 "requires": [],
1964 "uses": [],
1965 "idx": 196
1966 },
1967 {
1968 "path": "../packages/core/src/app/bind/BaseBinding.js",
1969 "requires": [
1970 196
1971 ],
1972 "uses": [],
1973 "idx": 197
1974 },
1975 {
1976 "path": "../packages/core/src/app/bind/Binding.js",
1977 "requires": [
1978 197
1979 ],
1980 "uses": [],
1981 "idx": 198
1982 },
1983 {
1984 "path": "../packages/core/src/app/bind/AbstractStub.js",
1985 "requires": [
1986 196,
1987 198
1988 ],
1989 "uses": [],
1990 "idx": 199
1991 },
1992 {
1993 "path": "../packages/core/src/app/bind/Stub.js",
1994 "requires": [
1995 198,
1996 199
1997 ],
1998 "uses": [
1999 204
2000 ],
2001 "idx": 200
2002 },
2003 {
2004 "path": "../packages/core/src/app/bind/LinkStub.js",
2005 "requires": [
2006 200
2007 ],
2008 "uses": [],
2009 "idx": 201
2010 },
2011 {
2012 "path": "../packages/core/src/app/bind/RootStub.js",
2013 "requires": [
2014 199,
2015 200,
2016 201
2017 ],
2018 "uses": [],
2019 "idx": 202
2020 },
2021 {
2022 "path": "../packages/core/src/app/bind/Multi.js",
2023 "requires": [
2024 197
2025 ],
2026 "uses": [],
2027 "idx": 203
2028 },
2029 {
2030 "path": "../packages/core/src/app/bind/Formula.js",
2031 "requires": [
2032 22,
2033 196
2034 ],
2035 "uses": [],
2036 "idx": 204
2037 },
2038 {
2039 "path": "../packages/core/src/app/bind/Template.js",
2040 "requires": [
2041 84
2042 ],
2043 "uses": [],
2044 "idx": 205
2045 },
2046 {
2047 "path": "../packages/core/src/app/bind/TemplateBinding.js",
2048 "requires": [
2049 197,
2050 203,
2051 205
2052 ],
2053 "uses": [],
2054 "idx": 206
2055 },
2056 {
2057 "path": "../packages/core/src/data/ChainedStore.js",
2058 "requires": [
2059 137,
2060 163
2061 ],
2062 "uses": [
2063 85,
2064 175
2065 ],
2066 "idx": 207
2067 },
2068 {
2069 "path": "../packages/core/src/app/ViewModel.js",
2070 "requires": [
2071 3,
2072 12,
2073 187,
2074 195,
2075 201,
2076 202,
2077 203,
2078 204,
2079 206,
2080 207
2081 ],
2082 "uses": [
2083 1,
2084 136
2085 ],
2086 "idx": 208
2087 },
2088 {
2089 "path": "../packages/core/src/app/domain/Controller.js",
2090 "requires": [
2091 89,
2092 181
2093 ],
2094 "uses": [
2095 123
2096 ],
2097 "idx": 209
2098 },
2099 {
2100 "path": "../packages/core/src/direct/Manager.js",
2101 "requires": [
2102 4,
2103 55
2104 ],
2105 "uses": [
2106 85
2107 ],
2108 "idx": 210
2109 },
2110 {
2111 "path": "../packages/core/src/direct/Provider.js",
2112 "requires": [
2113 4,
2114 210
2115 ],
2116 "uses": [],
2117 "idx": 211
2118 },
2119 {
2120 "path": "../packages/core/src/app/domain/Direct.js",
2121 "requires": [
2122 89,
2123 211
2124 ],
2125 "uses": [],
2126 "idx": 212
2127 },
2128 {
2129 "path": "../packages/core/src/data/PageMap.js",
2130 "requires": [
2131 22
2132 ],
2133 "uses": [],
2134 "idx": 213
2135 },
2136 {
2137 "path": "../packages/core/src/data/BufferedStore.js",
2138 "requires": [
2139 50,
2140 53,
2141 126,
2142 162,
2143 213
2144 ],
2145 "uses": [
2146 169,
2147 170,
2148 171
2149 ],
2150 "idx": 214
2151 },
2152 {
2153 "path": "../packages/core/src/data/proxy/Direct.js",
2154 "requires": [
2155 164,
2156 210
2157 ],
2158 "uses": [],
2159 "idx": 215
2160 },
2161 {
2162 "path": "../packages/core/src/data/DirectStore.js",
2163 "requires": [
2164 172,
2165 215
2166 ],
2167 "uses": [],
2168 "idx": 216
2169 },
2170 {
2171 "path": "../packages/core/src/data/JsonP.js",
2172 "requires": [],
2173 "uses": [
2174 76
2175 ],
2176 "idx": 217
2177 },
2178 {
2179 "path": "../packages/core/src/data/proxy/JsonP.js",
2180 "requires": [
2181 164,
2182 217
2183 ],
2184 "uses": [],
2185 "idx": 218
2186 },
2187 {
2188 "path": "../packages/core/src/data/JsonPStore.js",
2189 "requires": [
2190 166,
2191 172,
2192 218
2193 ],
2194 "uses": [],
2195 "idx": 219
2196 },
2197 {
2198 "path": "../packages/core/src/data/JsonStore.js",
2199 "requires": [
2200 165,
2201 166,
2202 167,
2203 172
2204 ],
2205 "uses": [],
2206 "idx": 220
2207 },
2208 {
2209 "path": "../packages/core/src/data/ModelManager.js",
2210 "requires": [
2211 136
2212 ],
2213 "uses": [
2214 155
2215 ],
2216 "idx": 221
2217 },
2218 {
2219 "path": "../packages/core/src/data/NodeInterface.js",
2220 "requires": [
2221 4,
2222 148,
2223 150,
2224 152,
2225 167
2226 ],
2227 "uses": [
2228 136
2229 ],
2230 "idx": 222
2231 },
2232 {
2233 "path": "../packages/core/src/mixin/Queryable.js",
2234 "requires": [],
2235 "uses": [
2236 23
2237 ],
2238 "idx": 223
2239 },
2240 {
2241 "path": "../packages/core/src/data/TreeModel.js",
2242 "requires": [
2243 155,
2244 222,
2245 223
2246 ],
2247 "uses": [],
2248 "idx": 224
2249 },
2250 {
2251 "path": "../packages/core/src/data/NodeStore.js",
2252 "requires": [
2253 172,
2254 222,
2255 224
2256 ],
2257 "uses": [
2258 155
2259 ],
2260 "idx": 225
2261 },
2262 {
2263 "path": "../packages/core/src/data/Request.js",
2264 "requires": [],
2265 "uses": [],
2266 "idx": 226
2267 },
2268 {
2269 "path": "../packages/core/src/data/TreeStore.js",
2270 "requires": [
2271 53,
2272 172,
2273 222,
2274 224
2275 ],
2276 "uses": [
2277 155
2278 ],
2279 "idx": 227
2280 },
2281 {
2282 "path": "../packages/core/src/data/Types.js",
2283 "requires": [
2284 145
2285 ],
2286 "uses": [],
2287 "idx": 228
2288 },
2289 {
2290 "path": "../packages/core/src/data/Validation.js",
2291 "requires": [
2292 155
2293 ],
2294 "uses": [],
2295 "idx": 229
2296 },
2297 {
2298 "path": "../packages/core/src/dom/Helper.js",
2299 "requires": [],
2300 "uses": [
2301 85
2302 ],
2303 "idx": 230
2304 },
2305 {
2306 "path": "../packages/core/src/dom/Query.js",
2307 "requires": [
2308 21,
2309 230
2310 ],
2311 "uses": [
2312 22
2313 ],
2314 "idx": 231
2315 },
2316 {
2317 "path": "../packages/core/src/data/reader/Xml.js",
2318 "requires": [
2319 157,
2320 231
2321 ],
2322 "uses": [],
2323 "idx": 232
2324 },
2325 {
2326 "path": "../packages/core/src/data/writer/Xml.js",
2327 "requires": [
2328 158
2329 ],
2330 "uses": [],
2331 "idx": 233
2332 },
2333 {
2334 "path": "../packages/core/src/data/XmlStore.js",
2335 "requires": [
2336 165,
2337 172,
2338 232,
2339 233
2340 ],
2341 "uses": [],
2342 "idx": 234
2343 },
2344 {
2345 "path": "../packages/core/src/data/identifier/Negative.js",
2346 "requires": [
2347 154
2348 ],
2349 "uses": [],
2350 "idx": 235
2351 },
2352 {
2353 "path": "../packages/core/src/data/identifier/Uuid.js",
2354 "requires": [
2355 153
2356 ],
2357 "uses": [],
2358 "idx": 236
2359 },
2360 {
2361 "path": "../packages/core/src/data/proxy/WebStorage.js",
2362 "requires": [
2363 154,
2364 160
2365 ],
2366 "uses": [
2367 53,
2368 85,
2369 156
2370 ],
2371 "idx": 237
2372 },
2373 {
2374 "path": "../packages/core/src/data/proxy/LocalStorage.js",
2375 "requires": [
2376 237
2377 ],
2378 "uses": [],
2379 "idx": 238
2380 },
2381 {
2382 "path": "../packages/core/src/data/proxy/Rest.js",
2383 "requires": [
2384 165
2385 ],
2386 "uses": [],
2387 "idx": 239
2388 },
2389 {
2390 "path": "../packages/core/src/data/proxy/SessionStorage.js",
2391 "requires": [
2392 237
2393 ],
2394 "uses": [],
2395 "idx": 240
2396 },
2397 {
2398 "path": "../packages/core/src/data/validator/Bound.js",
2399 "requires": [
2400 146
2401 ],
2402 "uses": [
2403 85
2404 ],
2405 "idx": 241
2406 },
2407 {
2408 "path": "../packages/core/src/data/validator/Format.js",
2409 "requires": [
2410 146
2411 ],
2412 "uses": [],
2413 "idx": 242
2414 },
2415 {
2416 "path": "../packages/core/src/data/validator/Email.js",
2417 "requires": [
2418 242
2419 ],
2420 "uses": [],
2421 "idx": 243
2422 },
2423 {
2424 "path": "../packages/core/src/data/validator/List.js",
2425 "requires": [
2426 146
2427 ],
2428 "uses": [],
2429 "idx": 244
2430 },
2431 {
2432 "path": "../packages/core/src/data/validator/Exclusion.js",
2433 "requires": [
2434 244
2435 ],
2436 "uses": [],
2437 "idx": 245
2438 },
2439 {
2440 "path": "../packages/core/src/data/validator/Inclusion.js",
2441 "requires": [
2442 244
2443 ],
2444 "uses": [],
2445 "idx": 246
2446 },
2447 {
2448 "path": "../packages/core/src/data/validator/Length.js",
2449 "requires": [
2450 241
2451 ],
2452 "uses": [],
2453 "idx": 247
2454 },
2455 {
2456 "path": "../packages/core/src/data/validator/Presence.js",
2457 "requires": [
2458 146
2459 ],
2460 "uses": [],
2461 "idx": 248
2462 },
2463 {
2464 "path": "../packages/core/src/data/validator/Range.js",
2465 "requires": [
2466 241
2467 ],
2468 "uses": [],
2469 "idx": 249
2470 },
2471 {
2472 "path": "../packages/core/src/direct/Event.js",
2473 "requires": [],
2474 "uses": [],
2475 "idx": 250
2476 },
2477 {
2478 "path": "../packages/core/src/direct/RemotingEvent.js",
2479 "requires": [
2480 250
2481 ],
2482 "uses": [
2483 210
2484 ],
2485 "idx": 251
2486 },
2487 {
2488 "path": "../packages/core/src/direct/ExceptionEvent.js",
2489 "requires": [
2490 251
2491 ],
2492 "uses": [],
2493 "idx": 252
2494 },
2495 {
2496 "path": "../packages/core/src/direct/JsonProvider.js",
2497 "requires": [
2498 211
2499 ],
2500 "uses": [
2501 210,
2502 252
2503 ],
2504 "idx": 253
2505 },
2506 {
2507 "path": "../packages/core/src/direct/PollingProvider.js",
2508 "requires": [
2509 18,
2510 56,
2511 252,
2512 253
2513 ],
2514 "uses": [
2515 210,
2516 323
2517 ],
2518 "idx": 254
2519 },
2520 {
2521 "path": "../packages/core/src/direct/RemotingMethod.js",
2522 "requires": [],
2523 "uses": [],
2524 "idx": 255
2525 },
2526 {
2527 "path": "../packages/core/src/direct/Transaction.js",
2528 "requires": [],
2529 "uses": [],
2530 "idx": 256
2531 },
2532 {
2533 "path": "../packages/core/src/direct/RemotingProvider.js",
2534 "requires": [
2535 1,
2536 55,
2537 210,
2538 253,
2539 255,
2540 256
2541 ],
2542 "uses": [
2543 18,
2544 77,
2545 252
2546 ],
2547 "idx": 257
2548 },
2549 {
2550 "path": "../packages/core/src/dom/GarbageCollector.js",
2551 "requires": [],
2552 "uses": [
2553 49
2554 ],
2555 "idx": 258
2556 },
2557 {
2558 "path": "../packages/core/src/event/gesture/Recognizer.js",
2559 "requires": [
2560 3,
2561 37
2562 ],
2563 "uses": [],
2564 "idx": 259
2565 },
2566 {
2567 "path": "../packages/core/src/event/gesture/SingleTouch.js",
2568 "requires": [
2569 259
2570 ],
2571 "uses": [],
2572 "idx": 260
2573 },
2574 {
2575 "path": "../packages/core/src/event/gesture/DoubleTap.js",
2576 "requires": [
2577 260
2578 ],
2579 "uses": [],
2580 "idx": 261
2581 },
2582 {
2583 "path": "../packages/core/src/event/gesture/Drag.js",
2584 "requires": [
2585 260
2586 ],
2587 "uses": [],
2588 "idx": 262
2589 },
2590 {
2591 "path": "../packages/core/src/event/gesture/Swipe.js",
2592 "requires": [
2593 260
2594 ],
2595 "uses": [],
2596 "idx": 263
2597 },
2598 {
2599 "path": "../packages/core/src/event/gesture/EdgeSwipe.js",
2600 "requires": [
2601 263
2602 ],
2603 "uses": [
2604 49
2605 ],
2606 "idx": 264
2607 },
2608 {
2609 "path": "../packages/core/src/event/gesture/LongPress.js",
2610 "requires": [
2611 260
2612 ],
2613 "uses": [],
2614 "idx": 265
2615 },
2616 {
2617 "path": "../packages/core/src/event/gesture/MultiTouch.js",
2618 "requires": [
2619 259
2620 ],
2621 "uses": [],
2622 "idx": 266
2623 },
2624 {
2625 "path": "../packages/core/src/event/gesture/Pinch.js",
2626 "requires": [
2627 266
2628 ],
2629 "uses": [],
2630 "idx": 267
2631 },
2632 {
2633 "path": "../packages/core/src/event/gesture/Rotate.js",
2634 "requires": [
2635 266
2636 ],
2637 "uses": [],
2638 "idx": 268
2639 },
2640 {
2641 "path": "../packages/core/src/event/gesture/Tap.js",
2642 "requires": [
2643 260
2644 ],
2645 "uses": [],
2646 "idx": 269
2647 },
2648 {
2649 "path": "../packages/core/src/event/publisher/Focus.js",
2650 "requires": [
2651 36,
2652 49,
2653 76
2654 ],
2655 "uses": [
2656 35
2657 ],
2658 "idx": 270
2659 },
2660 {
2661 "path": "../packages/core/src/fx/State.js",
2662 "requires": [],
2663 "uses": [],
2664 "idx": 271
2665 },
2666 {
2667 "path": "../packages/core/src/fx/animation/Abstract.js",
2668 "requires": [
2669 24,
2670 271
2671 ],
2672 "uses": [],
2673 "idx": 272
2674 },
2675 {
2676 "path": "../packages/core/src/fx/animation/Slide.js",
2677 "requires": [
2678 272
2679 ],
2680 "uses": [],
2681 "idx": 273
2682 },
2683 {
2684 "path": "../packages/core/src/fx/animation/SlideOut.js",
2685 "requires": [
2686 273
2687 ],
2688 "uses": [],
2689 "idx": 274
2690 },
2691 {
2692 "path": "../packages/core/src/fx/animation/Fade.js",
2693 "requires": [
2694 272
2695 ],
2696 "uses": [],
2697 "idx": 275
2698 },
2699 {
2700 "path": "../packages/core/src/fx/animation/FadeOut.js",
2701 "requires": [
2702 275
2703 ],
2704 "uses": [],
2705 "idx": 276
2706 },
2707 {
2708 "path": "../packages/core/src/fx/animation/Flip.js",
2709 "requires": [
2710 272
2711 ],
2712 "uses": [],
2713 "idx": 277
2714 },
2715 {
2716 "path": "../packages/core/src/fx/animation/Pop.js",
2717 "requires": [
2718 272
2719 ],
2720 "uses": [],
2721 "idx": 278
2722 },
2723 {
2724 "path": "../packages/core/src/fx/animation/PopOut.js",
2725 "requires": [
2726 278
2727 ],
2728 "uses": [],
2729 "idx": 279
2730 },
2731 {
2732 "path": "../packages/core/src/fx/Animation.js",
2733 "requires": [
2734 273,
2735 274,
2736 275,
2737 276,
2738 277,
2739 278,
2740 279
2741 ],
2742 "uses": [
2743 272
2744 ],
2745 "idx": 280
2746 },
2747 {
2748 "path": "../packages/core/src/fx/runner/Css.js",
2749 "requires": [
2750 24,
2751 280
2752 ],
2753 "uses": [],
2754 "idx": 281
2755 },
2756 {
2757 "path": "../packages/core/src/fx/runner/CssTransition.js",
2758 "requires": [
2759 19,
2760 281
2761 ],
2762 "uses": [
2763 280
2764 ],
2765 "idx": 282
2766 },
2767 {
2768 "path": "../packages/core/src/fx/Runner.js",
2769 "requires": [
2770 282
2771 ],
2772 "uses": [],
2773 "idx": 283
2774 },
2775 {
2776 "path": "../packages/core/src/fx/animation/Cube.js",
2777 "requires": [
2778 272
2779 ],
2780 "uses": [],
2781 "idx": 284
2782 },
2783 {
2784 "path": "../packages/core/src/fx/animation/Wipe.js",
2785 "requires": [
2786 280
2787 ],
2788 "uses": [],
2789 "idx": 285
2790 },
2791 {
2792 "path": "../packages/core/src/fx/animation/WipeOut.js",
2793 "requires": [
2794 285
2795 ],
2796 "uses": [],
2797 "idx": 286
2798 },
2799 {
2800 "path": "../packages/core/src/fx/easing/EaseIn.js",
2801 "requires": [
2802 98
2803 ],
2804 "uses": [],
2805 "idx": 287
2806 },
2807 {
2808 "path": "../packages/core/src/fx/easing/Easing.js",
2809 "requires": [
2810 98
2811 ],
2812 "uses": [],
2813 "idx": 288
2814 },
2815 {
2816 "path": "../packages/core/src/fx/layout/card/Abstract.js",
2817 "requires": [
2818 24
2819 ],
2820 "uses": [],
2821 "idx": 289
2822 },
2823 {
2824 "path": "../packages/core/src/fx/layout/card/Style.js",
2825 "requires": [
2826 280,
2827 289
2828 ],
2829 "uses": [
2830 282
2831 ],
2832 "idx": 290
2833 },
2834 {
2835 "path": "../packages/core/src/fx/layout/card/Slide.js",
2836 "requires": [
2837 290
2838 ],
2839 "uses": [],
2840 "idx": 291
2841 },
2842 {
2843 "path": "../packages/core/src/fx/layout/card/Cover.js",
2844 "requires": [
2845 290
2846 ],
2847 "uses": [],
2848 "idx": 292
2849 },
2850 {
2851 "path": "../packages/core/src/fx/layout/card/Reveal.js",
2852 "requires": [
2853 290
2854 ],
2855 "uses": [],
2856 "idx": 293
2857 },
2858 {
2859 "path": "../packages/core/src/fx/layout/card/Fade.js",
2860 "requires": [
2861 290
2862 ],
2863 "uses": [],
2864 "idx": 294
2865 },
2866 {
2867 "path": "../packages/core/src/fx/layout/card/Flip.js",
2868 "requires": [
2869 290
2870 ],
2871 "uses": [],
2872 "idx": 295
2873 },
2874 {
2875 "path": "../packages/core/src/fx/layout/card/Pop.js",
2876 "requires": [
2877 290
2878 ],
2879 "uses": [],
2880 "idx": 296
2881 },
2882 {
2883 "path": "../packages/core/src/fx/layout/card/Scroll.js",
2884 "requires": [
2885 98,
2886 289
2887 ],
2888 "uses": [
2889 19
2890 ],
2891 "idx": 297
2892 },
2893 {
2894 "path": "../packages/core/src/fx/layout/Card.js",
2895 "requires": [
2896 291,
2897 292,
2898 293,
2899 294,
2900 295,
2901 296,
2902 297
2903 ],
2904 "uses": [
2905 289
2906 ],
2907 "idx": 298
2908 },
2909 {
2910 "path": "../packages/core/src/fx/layout/card/Cube.js",
2911 "requires": [
2912 290
2913 ],
2914 "uses": [],
2915 "idx": 299
2916 },
2917 {
2918 "path": "../packages/core/src/fx/layout/card/ScrollCover.js",
2919 "requires": [
2920 297
2921 ],
2922 "uses": [],
2923 "idx": 300
2924 },
2925 {
2926 "path": "../packages/core/src/fx/layout/card/ScrollReveal.js",
2927 "requires": [
2928 297
2929 ],
2930 "uses": [],
2931 "idx": 301
2932 },
2933 {
2934 "path": "../packages/core/src/fx/runner/CssAnimation.js",
2935 "requires": [
2936 281
2937 ],
2938 "uses": [
2939 280
2940 ],
2941 "idx": 302
2942 },
2943 {
2944 "path": "../packages/core/src/list/AbstractTreeItem.js",
2945 "requires": [
2946 81
2947 ],
2948 "uses": [],
2949 "idx": 303
2950 },
2951 {
2952 "path": "../packages/core/src/list/RootTreeItem.js",
2953 "requires": [
2954 303
2955 ],
2956 "uses": [],
2957 "idx": 304
2958 },
2959 {
2960 "path": "../packages/core/src/list/TreeItem.js",
2961 "requires": [
2962 303
2963 ],
2964 "uses": [],
2965 "idx": 305
2966 },
2967 {
2968 "path": "../packages/core/src/list/Tree.js",
2969 "requires": [
2970 81,
2971 195,
2972 304,
2973 305
2974 ],
2975 "uses": [
2976 175
2977 ],
2978 "idx": 306
2979 },
2980 {
2981 "path": "../packages/core/src/mixin/Container.js",
2982 "requires": [
2983 0
2984 ],
2985 "uses": [
2986 20
2987 ],
2988 "idx": 307
2989 },
2990 {
2991 "path": "../packages/core/src/mixin/Hookable.js",
2992 "requires": [
2993 0
2994 ],
2995 "uses": [],
2996 "idx": 308
2997 },
2998 {
2999 "path": "../packages/core/src/mixin/Mashup.js",
3000 "requires": [
3001 0
3002 ],
3003 "uses": [],
3004 "idx": 309
3005 },
3006 {
3007 "path": "../packages/core/src/mixin/Responsive.js",
3008 "requires": [
3009 0,
3010 76
3011 ],
3012 "uses": [
3013 49
3014 ],
3015 "idx": 310
3016 },
3017 {
3018 "path": "../packages/core/src/mixin/Selectable.js",
3019 "requires": [
3020 0
3021 ],
3022 "uses": [
3023 55
3024 ],
3025 "idx": 311
3026 },
3027 {
3028 "path": "../packages/core/src/mixin/Traversable.js",
3029 "requires": [
3030 0
3031 ],
3032 "uses": [],
3033 "idx": 312
3034 },
3035 {
3036 "path": "../packages/core/src/perf/Accumulator.js",
3037 "requires": [
3038 88
3039 ],
3040 "uses": [],
3041 "idx": 313
3042 },
3043 {
3044 "path": "../packages/core/src/perf/Monitor.js",
3045 "requires": [
3046 313
3047 ],
3048 "uses": [],
3049 "idx": 314
3050 },
3051 {
3052 "path": "../packages/core/src/plugin/Abstract.js",
3053 "requires": [],
3054 "uses": [],
3055 "idx": 315
3056 },
3057 {
3058 "path": "../packages/core/src/plugin/LazyItems.js",
3059 "requires": [
3060 315
3061 ],
3062 "uses": [],
3063 "idx": 316
3064 },
3065 {
3066 "path": "../packages/core/src/util/Base64.js",
3067 "requires": [],
3068 "uses": [],
3069 "idx": 317
3070 },
3071 {
3072 "path": "../packages/core/src/util/DelimitedValue.js",
3073 "requires": [],
3074 "uses": [],
3075 "idx": 318
3076 },
3077 {
3078 "path": "../packages/core/src/util/CSV.js",
3079 "requires": [
3080 318
3081 ],
3082 "uses": [],
3083 "idx": 319
3084 },
3085 {
3086 "path": "../packages/core/src/util/ItemCollection.js",
3087 "requires": [
3088 55
3089 ],
3090 "uses": [],
3091 "idx": 320
3092 },
3093 {
3094 "path": "../packages/core/src/util/LocalStorage.js",
3095 "requires": [],
3096 "uses": [],
3097 "idx": 321
3098 },
3099 {
3100 "path": "../packages/core/src/util/TSV.js",
3101 "requires": [
3102 318
3103 ],
3104 "uses": [],
3105 "idx": 322
3106 },
3107 {
3108 "path": "../packages/core/src/util/TaskManager.js",
3109 "requires": [
3110 56
3111 ],
3112 "uses": [],
3113 "idx": 323
3114 },
3115 {
3116 "path": "../packages/core/src/util/TextMetrics.js",
3117 "requires": [
3118 49
3119 ],
3120 "uses": [],
3121 "idx": 324
3122 },
3123 {
3124 "path": "../packages/core/src/util/paintmonitor/OverflowChange.js",
3125 "requires": [
3126 45
3127 ],
3128 "uses": [],
3129 "idx": 325
3130 },
3131 {
3132 "path": "../classic/classic/src/Action.js",
3133 "requires": [],
3134 "uses": [],
3135 "idx": 326
3136 },
3137 {
3138 "path": "../classic/classic/src/ElementLoader.js",
3139 "requires": [
3140 51
3141 ],
3142 "uses": [
3143 17,
3144 18
3145 ],
3146 "idx": 327
3147 },
3148 {
3149 "path": "../classic/classic/src/ComponentLoader.js",
3150 "requires": [
3151 327
3152 ],
3153 "uses": [],
3154 "idx": 328
3155 },
3156 {
3157 "path": "../classic/classic/src/layout/SizeModel.js",
3158 "requires": [],
3159 "uses": [],
3160 "idx": 329
3161 },
3162 {
3163 "path": "../classic/classic/src/layout/Layout.js",
3164 "requires": [
3165 12,
3166 88,
3167 329
3168 ],
3169 "uses": [
3170 554
3171 ],
3172 "idx": 330
3173 },
3174 {
3175 "path": "../classic/classic/src/layout/container/Container.js",
3176 "requires": [
3177 88,
3178 111,
3179 330
3180 ],
3181 "uses": [
3182 230
3183 ],
3184 "idx": 331
3185 },
3186 {
3187 "path": "../classic/classic/src/layout/container/Auto.js",
3188 "requires": [
3189 331
3190 ],
3191 "uses": [
3192 88
3193 ],
3194 "idx": 332
3195 },
3196 {
3197 "path": "../classic/classic/src/ZIndexManager.js",
3198 "requires": [
3199 76,
3200 169,
3201 170
3202 ],
3203 "uses": [
3204 49,
3205 127
3206 ],
3207 "idx": 333
3208 },
3209 {
3210 "path": "../classic/classic/src/container/Container.js",
3211 "requires": [
3212 55,
3213 119,
3214 223,
3215 307,
3216 320,
3217 332,
3218 333
3219 ],
3220 "uses": [
3221 12,
3222 20,
3223 23
3224 ],
3225 "idx": 334
3226 },
3227 {
3228 "path": "../classic/classic/src/layout/container/Editor.js",
3229 "requires": [
3230 331
3231 ],
3232 "uses": [],
3233 "idx": 335
3234 },
3235 {
3236 "path": "../classic/classic/src/Editor.js",
3237 "requires": [
3238 334,
3239 335
3240 ],
3241 "uses": [
3242 1,
3243 20
3244 ],
3245 "idx": 336
3246 },
3247 {
3248 "path": "../classic/classic/src/EventManager.js",
3249 "requires": [],
3250 "uses": [
3251 76
3252 ],
3253 "idx": 337
3254 },
3255 {
3256 "path": "../classic/classic/src/Img.js",
3257 "requires": [
3258 119
3259 ],
3260 "uses": [],
3261 "idx": 338
3262 },
3263 {
3264 "path": "../classic/classic/src/util/StoreHolder.js",
3265 "requires": [
3266 175
3267 ],
3268 "uses": [],
3269 "idx": 339
3270 },
3271 {
3272 "path": "../classic/classic/src/LoadMask.js",
3273 "requires": [
3274 119,
3275 339
3276 ],
3277 "uses": [
3278 49,
3279 76,
3280 175
3281 ],
3282 "idx": 340
3283 },
3284 {
3285 "path": "../classic/classic/src/layout/component/Component.js",
3286 "requires": [
3287 330
3288 ],
3289 "uses": [],
3290 "idx": 341
3291 },
3292 {
3293 "path": "../classic/classic/src/layout/component/Auto.js",
3294 "requires": [
3295 341
3296 ],
3297 "uses": [],
3298 "idx": 342
3299 },
3300 {
3301 "path": "../classic/classic/src/layout/component/ProgressBar.js",
3302 "requires": [
3303 342
3304 ],
3305 "uses": [],
3306 "idx": 343
3307 },
3308 {
3309 "path": "../classic/classic/src/ProgressBar.js",
3310 "requires": [
3311 82,
3312 85,
3313 92,
3314 119,
3315 323,
3316 343
3317 ],
3318 "uses": [
3319 72
3320 ],
3321 "idx": 344
3322 },
3323 {
3324 "path": "../classic/classic/src/dom/ButtonElement.js",
3325 "requires": [
3326 49
3327 ],
3328 "uses": [],
3329 "idx": 345
3330 },
3331 {
3332 "path": "../classic/classic/src/button/Manager.js",
3333 "requires": [],
3334 "uses": [],
3335 "idx": 346
3336 },
3337 {
3338 "path": "../classic/classic/src/menu/Manager.js",
3339 "requires": [],
3340 "uses": [
3341 20,
3342 119,
3343 519
3344 ],
3345 "idx": 347
3346 },
3347 {
3348 "path": "../classic/classic/src/util/ClickRepeater.js",
3349 "requires": [
3350 51
3351 ],
3352 "uses": [],
3353 "idx": 348
3354 },
3355 {
3356 "path": "../classic/classic/src/button/Button.js",
3357 "requires": [
3358 118,
3359 119,
3360 223,
3361 324,
3362 345,
3363 346,
3364 347,
3365 348
3366 ],
3367 "uses": [
3368 467
3369 ],
3370 "idx": 349
3371 },
3372 {
3373 "path": "../classic/classic/src/button/Split.js",
3374 "requires": [
3375 349
3376 ],
3377 "uses": [
3378 49
3379 ],
3380 "idx": 350
3381 },
3382 {
3383 "path": "../classic/classic/src/button/Cycle.js",
3384 "requires": [
3385 350
3386 ],
3387 "uses": [],
3388 "idx": 351
3389 },
3390 {
3391 "path": "../classic/classic/src/layout/container/SegmentedButton.js",
3392 "requires": [
3393 331
3394 ],
3395 "uses": [],
3396 "idx": 352
3397 },
3398 {
3399 "path": "../classic/classic/src/button/Segmented.js",
3400 "requires": [
3401 334,
3402 349,
3403 352
3404 ],
3405 "uses": [],
3406 "idx": 353
3407 },
3408 {
3409 "path": "../classic/classic/src/panel/Bar.js",
3410 "requires": [
3411 334
3412 ],
3413 "uses": [],
3414 "idx": 354
3415 },
3416 {
3417 "path": "../classic/classic/src/panel/Title.js",
3418 "requires": [
3419 119
3420 ],
3421 "uses": [],
3422 "idx": 355
3423 },
3424 {
3425 "path": "../classic/classic/src/panel/Tool.js",
3426 "requires": [
3427 119
3428 ],
3429 "uses": [
3430 467
3431 ],
3432 "idx": 356
3433 },
3434 {
3435 "path": "../classic/classic/src/util/KeyMap.js",
3436 "requires": [],
3437 "uses": [],
3438 "idx": 357
3439 },
3440 {
3441 "path": "../classic/classic/src/util/KeyNav.js",
3442 "requires": [
3443 357
3444 ],
3445 "uses": [],
3446 "idx": 358
3447 },
3448 {
3449 "path": "../classic/classic/src/util/FocusableContainer.js",
3450 "requires": [
3451 0,
3452 358
3453 ],
3454 "uses": [
3455 119
3456 ],
3457 "idx": 359
3458 },
3459 {
3460 "path": "../classic/classic/src/panel/Header.js",
3461 "requires": [
3462 195,
3463 342,
3464 354,
3465 355,
3466 356,
3467 359
3468 ],
3469 "uses": [
3470 20,
3471 119
3472 ],
3473 "idx": 360
3474 },
3475 {
3476 "path": "../classic/classic/src/layout/container/boxOverflow/None.js",
3477 "requires": [
3478 12
3479 ],
3480 "uses": [],
3481 "idx": 361
3482 },
3483 {
3484 "path": "../classic/classic/src/layout/container/boxOverflow/Scroller.js",
3485 "requires": [
3486 4,
3487 49,
3488 348,
3489 361
3490 ],
3491 "uses": [],
3492 "idx": 362
3493 },
3494 {
3495 "path": "../classic/classic/src/dd/DragDropManager.js",
3496 "requires": [
3497 33
3498 ],
3499 "uses": [
3500 395,
3501 467
3502 ],
3503 "idx": 363
3504 },
3505 {
3506 "path": "../classic/classic/src/resizer/Splitter.js",
3507 "requires": [
3508 88,
3509 119
3510 ],
3511 "uses": [
3512 391
3513 ],
3514 "idx": 364
3515 },
3516 {
3517 "path": "../classic/classic/src/layout/container/Box.js",
3518 "requires": [
3519 84,
3520 331,
3521 361,
3522 362,
3523 363,
3524 364
3525 ],
3526 "uses": [
3527 12,
3528 195,
3529 329,
3530 342
3531 ],
3532 "idx": 365
3533 },
3534 {
3535 "path": "../classic/classic/src/layout/container/HBox.js",
3536 "requires": [
3537 365
3538 ],
3539 "uses": [],
3540 "idx": 366
3541 },
3542 {
3543 "path": "../classic/classic/src/layout/container/VBox.js",
3544 "requires": [
3545 365
3546 ],
3547 "uses": [],
3548 "idx": 367
3549 },
3550 {
3551 "path": "../classic/classic/src/toolbar/Toolbar.js",
3552 "requires": [
3553 195,
3554 334,
3555 342,
3556 359,
3557 366,
3558 367
3559 ],
3560 "uses": [
3561 449,
3562 470,
3563 602
3564 ],
3565 "idx": 368
3566 },
3567 {
3568 "path": "../classic/classic/src/dd/DragDrop.js",
3569 "requires": [
3570 363
3571 ],
3572 "uses": [
3573 49
3574 ],
3575 "idx": 369
3576 },
3577 {
3578 "path": "../classic/classic/src/dd/DD.js",
3579 "requires": [
3580 363,
3581 369
3582 ],
3583 "uses": [
3584 49
3585 ],
3586 "idx": 370
3587 },
3588 {
3589 "path": "../classic/classic/src/dd/DDProxy.js",
3590 "requires": [
3591 370
3592 ],
3593 "uses": [
3594 363
3595 ],
3596 "idx": 371
3597 },
3598 {
3599 "path": "../classic/classic/src/dd/StatusProxy.js",
3600 "requires": [
3601 119
3602 ],
3603 "uses": [],
3604 "idx": 372
3605 },
3606 {
3607 "path": "../classic/classic/src/dd/DragSource.js",
3608 "requires": [
3609 363,
3610 371,
3611 372
3612 ],
3613 "uses": [
3614 195,
3615 342
3616 ],
3617 "idx": 373
3618 },
3619 {
3620 "path": "../classic/classic/src/panel/Proxy.js",
3621 "requires": [],
3622 "uses": [
3623 49
3624 ],
3625 "idx": 374
3626 },
3627 {
3628 "path": "../classic/classic/src/panel/DD.js",
3629 "requires": [
3630 373,
3631 374
3632 ],
3633 "uses": [],
3634 "idx": 375
3635 },
3636 {
3637 "path": "../classic/classic/src/layout/component/Dock.js",
3638 "requires": [
3639 341
3640 ],
3641 "uses": [
3642 23,
3643 49,
3644 329
3645 ],
3646 "idx": 376
3647 },
3648 {
3649 "path": "../classic/classic/src/util/Memento.js",
3650 "requires": [],
3651 "uses": [],
3652 "idx": 377
3653 },
3654 {
3655 "path": "../classic/classic/src/container/DockingContainer.js",
3656 "requires": [
3657 49,
3658 55
3659 ],
3660 "uses": [
3661 23,
3662 230,
3663 320
3664 ],
3665 "idx": 378
3666 },
3667 {
3668 "path": "../classic/classic/src/panel/Panel.js",
3669 "requires": [
3670 49,
3671 55,
3672 72,
3673 88,
3674 334,
3675 357,
3676 360,
3677 368,
3678 375,
3679 376,
3680 377,
3681 378
3682 ],
3683 "uses": [
3684 1,
3685 20,
3686 84,
3687 91,
3688 92,
3689 119,
3690 195,
3691 230,
3692 332,
3693 342,
3694 356,
3695 358,
3696 411,
3697 471
3698 ],
3699 "idx": 379
3700 },
3701 {
3702 "path": "../classic/classic/src/layout/container/Table.js",
3703 "requires": [
3704 331
3705 ],
3706 "uses": [],
3707 "idx": 380
3708 },
3709 {
3710 "path": "../classic/classic/src/container/ButtonGroup.js",
3711 "requires": [
3712 359,
3713 379,
3714 380
3715 ],
3716 "uses": [],
3717 "idx": 381
3718 },
3719 {
3720 "path": "../classic/classic/src/container/Monitor.js",
3721 "requires": [],
3722 "uses": [
3723 55
3724 ],
3725 "idx": 382
3726 },
3727 {
3728 "path": "../classic/classic/src/plugin/Responsive.js",
3729 "requires": [
3730 310
3731 ],
3732 "uses": [],
3733 "idx": 383
3734 },
3735 {
3736 "path": "../classic/classic/src/plugin/Viewport.js",
3737 "requires": [
3738 383
3739 ],
3740 "uses": [
3741 49,
3742 109,
3743 329
3744 ],
3745 "idx": 384
3746 },
3747 {
3748 "path": "../classic/classic/src/container/Viewport.js",
3749 "requires": [
3750 310,
3751 334,
3752 384
3753 ],
3754 "uses": [],
3755 "idx": 385
3756 },
3757 {
3758 "path": "../classic/classic/src/layout/container/Anchor.js",
3759 "requires": [
3760 332
3761 ],
3762 "uses": [],
3763 "idx": 386
3764 },
3765 {
3766 "path": "../classic/classic/src/dashboard/Panel.js",
3767 "requires": [
3768 379
3769 ],
3770 "uses": [
3771 20
3772 ],
3773 "idx": 387
3774 },
3775 {
3776 "path": "../classic/classic/src/dashboard/Column.js",
3777 "requires": [
3778 334,
3779 386,
3780 387
3781 ],
3782 "uses": [],
3783 "idx": 388
3784 },
3785 {
3786 "path": "../classic/classic/src/layout/container/Column.js",
3787 "requires": [
3788 332
3789 ],
3790 "uses": [],
3791 "idx": 389
3792 },
3793 {
3794 "path": "../classic/classic/src/dd/DragTracker.js",
3795 "requires": [
3796 51
3797 ],
3798 "uses": [
3799 33,
3800 358
3801 ],
3802 "idx": 390
3803 },
3804 {
3805 "path": "../classic/classic/src/resizer/SplitterTracker.js",
3806 "requires": [
3807 33,
3808 390
3809 ],
3810 "uses": [
3811 49,
3812 98
3813 ],
3814 "idx": 391
3815 },
3816 {
3817 "path": "../classic/classic/src/layout/container/ColumnSplitterTracker.js",
3818 "requires": [
3819 391
3820 ],
3821 "uses": [],
3822 "idx": 392
3823 },
3824 {
3825 "path": "../classic/classic/src/layout/container/ColumnSplitter.js",
3826 "requires": [
3827 364,
3828 392
3829 ],
3830 "uses": [],
3831 "idx": 393
3832 },
3833 {
3834 "path": "../classic/classic/src/layout/container/Dashboard.js",
3835 "requires": [
3836 389,
3837 393
3838 ],
3839 "uses": [
3840 195,
3841 342
3842 ],
3843 "idx": 394
3844 },
3845 {
3846 "path": "../classic/classic/src/dd/DDTarget.js",
3847 "requires": [
3848 369
3849 ],
3850 "uses": [],
3851 "idx": 395
3852 },
3853 {
3854 "path": "../classic/classic/src/dd/ScrollManager.js",
3855 "requires": [
3856 363
3857 ],
3858 "uses": [],
3859 "idx": 396
3860 },
3861 {
3862 "path": "../classic/classic/src/dd/DropTarget.js",
3863 "requires": [
3864 395,
3865 396
3866 ],
3867 "uses": [],
3868 "idx": 397
3869 },
3870 {
3871 "path": "../classic/classic/src/dashboard/DropZone.js",
3872 "requires": [
3873 397
3874 ],
3875 "uses": [],
3876 "idx": 398
3877 },
3878 {
3879 "path": "../classic/classic/src/dashboard/Part.js",
3880 "requires": [
3881 3,
3882 12,
3883 128
3884 ],
3885 "uses": [],
3886 "idx": 399
3887 },
3888 {
3889 "path": "../classic/classic/src/dashboard/Dashboard.js",
3890 "requires": [
3891 379,
3892 388,
3893 394,
3894 398,
3895 399
3896 ],
3897 "uses": [
3898 12,
3899 114,
3900 127
3901 ],
3902 "idx": 400
3903 },
3904 {
3905 "path": "../classic/classic/src/dd/DragZone.js",
3906 "requires": [
3907 373
3908 ],
3909 "uses": [
3910 396,
3911 402
3912 ],
3913 "idx": 401
3914 },
3915 {
3916 "path": "../classic/classic/src/dd/Registry.js",
3917 "requires": [],
3918 "uses": [],
3919 "idx": 402
3920 },
3921 {
3922 "path": "../classic/classic/src/dd/DropZone.js",
3923 "requires": [
3924 397,
3925 402
3926 ],
3927 "uses": [
3928 363
3929 ],
3930 "idx": 403
3931 },
3932 {
3933 "path": "../classic/classic/src/dom/Layer.js",
3934 "requires": [
3935 49
3936 ],
3937 "uses": [
3938 230
3939 ],
3940 "idx": 404
3941 },
3942 {
3943 "path": "../classic/classic/src/enums.js",
3944 "requires": [],
3945 "uses": [],
3946 "idx": 405
3947 },
3948 {
3949 "path": "../classic/classic/src/event/publisher/MouseEnterLeave.js",
3950 "requires": [
3951 36
3952 ],
3953 "uses": [],
3954 "idx": 406
3955 },
3956 {
3957 "path": "../classic/classic/src/flash/Component.js",
3958 "requires": [
3959 119
3960 ],
3961 "uses": [],
3962 "idx": 407
3963 },
3964 {
3965 "path": "../classic/classic/src/form/action/Action.js",
3966 "requires": [],
3967 "uses": [],
3968 "idx": 408
3969 },
3970 {
3971 "path": "../classic/classic/src/form/action/Load.js",
3972 "requires": [
3973 17,
3974 408
3975 ],
3976 "uses": [
3977 18
3978 ],
3979 "idx": 409
3980 },
3981 {
3982 "path": "../classic/classic/src/form/action/Submit.js",
3983 "requires": [
3984 408
3985 ],
3986 "uses": [
3987 18,
3988 230
3989 ],
3990 "idx": 410
3991 },
3992 {
3993 "path": "../classic/classic/src/util/ComponentDragger.js",
3994 "requires": [
3995 390
3996 ],
3997 "uses": [
3998 33,
3999 49
4000 ],
4001 "idx": 411
4002 },
4003 {
4004 "path": "../classic/classic/src/util/FocusTrap.js",
4005 "requires": [
4006 0
4007 ],
4008 "uses": [],
4009 "idx": 412
4010 },
4011 {
4012 "path": "../classic/classic/src/window/Window.js",
4013 "requires": [
4014 33,
4015 379,
4016 411,
4017 412
4018 ],
4019 "uses": [],
4020 "idx": 413
4021 },
4022 {
4023 "path": "../classic/classic/src/form/Labelable.js",
4024 "requires": [
4025 0,
4026 88
4027 ],
4028 "uses": [
4029 49,
4030 466
4031 ],
4032 "idx": 414
4033 },
4034 {
4035 "path": "../classic/classic/src/form/field/Field.js",
4036 "requires": [],
4037 "uses": [],
4038 "idx": 415
4039 },
4040 {
4041 "path": "../classic/classic/src/form/field/Base.js",
4042 "requires": [
4043 1,
4044 88,
4045 119,
4046 414,
4047 415
4048 ],
4049 "uses": [
4050 230
4051 ],
4052 "idx": 416
4053 },
4054 {
4055 "path": "../classic/classic/src/form/field/VTypes.js",
4056 "requires": [],
4057 "uses": [],
4058 "idx": 417
4059 },
4060 {
4061 "path": "../classic/classic/src/form/trigger/Trigger.js",
4062 "requires": [
4063 12,
4064 348
4065 ],
4066 "uses": [
4067 49,
4068 88
4069 ],
4070 "idx": 418
4071 },
4072 {
4073 "path": "../classic/classic/src/form/field/Text.js",
4074 "requires": [
4075 324,
4076 416,
4077 417,
4078 418
4079 ],
4080 "uses": [
4081 84,
4082 85,
4083 92
4084 ],
4085 "idx": 419
4086 },
4087 {
4088 "path": "../classic/classic/src/form/field/TextArea.js",
4089 "requires": [
4090 1,
4091 88,
4092 419
4093 ],
4094 "uses": [
4095 84,
4096 324
4097 ],
4098 "idx": 420
4099 },
4100 {
4101 "path": "../classic/classic/src/window/MessageBox.js",
4102 "requires": [
4103 344,
4104 349,
4105 366,
4106 368,
4107 386,
4108 413,
4109 419,
4110 420
4111 ],
4112 "uses": [
4113 119,
4114 195,
4115 334,
4116 342,
4117 343,
4118 471
4119 ],
4120 "idx": 421
4121 },
4122 {
4123 "path": "../classic/classic/src/form/Basic.js",
4124 "requires": [
4125 1,
4126 51,
4127 55,
4128 139,
4129 409,
4130 410,
4131 421
4132 ],
4133 "uses": [
4134 382
4135 ],
4136 "idx": 422
4137 },
4138 {
4139 "path": "../classic/classic/src/form/FieldAncestor.js",
4140 "requires": [
4141 0,
4142 382
4143 ],
4144 "uses": [],
4145 "idx": 423
4146 },
4147 {
4148 "path": "../classic/classic/src/layout/component/field/FieldContainer.js",
4149 "requires": [
4150 342
4151 ],
4152 "uses": [],
4153 "idx": 424
4154 },
4155 {
4156 "path": "../classic/classic/src/form/FieldContainer.js",
4157 "requires": [
4158 334,
4159 414,
4160 423,
4161 424
4162 ],
4163 "uses": [],
4164 "idx": 425
4165 },
4166 {
4167 "path": "../classic/classic/src/layout/container/CheckboxGroup.js",
4168 "requires": [
4169 331
4170 ],
4171 "uses": [
4172 230
4173 ],
4174 "idx": 426
4175 },
4176 {
4177 "path": "../classic/classic/src/form/CheckboxManager.js",
4178 "requires": [
4179 55
4180 ],
4181 "uses": [],
4182 "idx": 427
4183 },
4184 {
4185 "path": "../classic/classic/src/form/field/Checkbox.js",
4186 "requires": [
4187 88,
4188 416,
4189 427
4190 ],
4191 "uses": [],
4192 "idx": 428
4193 },
4194 {
4195 "path": "../classic/classic/src/form/CheckboxGroup.js",
4196 "requires": [
4197 415,
4198 416,
4199 425,
4200 426,
4201 428
4202 ],
4203 "uses": [],
4204 "idx": 429
4205 },
4206 {
4207 "path": "../classic/classic/src/form/FieldSet.js",
4208 "requires": [
4209 334,
4210 423
4211 ],
4212 "uses": [
4213 49,
4214 91,
4215 119,
4216 195,
4217 230,
4218 342,
4219 356,
4220 386,
4221 428,
4222 557
4223 ],
4224 "idx": 430
4225 },
4226 {
4227 "path": "../classic/classic/src/form/Label.js",
4228 "requires": [
4229 84,
4230 119
4231 ],
4232 "uses": [],
4233 "idx": 431
4234 },
4235 {
4236 "path": "../classic/classic/src/form/Panel.js",
4237 "requires": [
4238 56,
4239 379,
4240 422,
4241 423
4242 ],
4243 "uses": [],
4244 "idx": 432
4245 },
4246 {
4247 "path": "../classic/classic/src/form/RadioManager.js",
4248 "requires": [
4249 55
4250 ],
4251 "uses": [],
4252 "idx": 433
4253 },
4254 {
4255 "path": "../classic/classic/src/form/field/Radio.js",
4256 "requires": [
4257 428,
4258 433
4259 ],
4260 "uses": [],
4261 "idx": 434
4262 },
4263 {
4264 "path": "../classic/classic/src/form/RadioGroup.js",
4265 "requires": [
4266 359,
4267 429,
4268 434
4269 ],
4270 "uses": [
4271 433
4272 ],
4273 "idx": 435
4274 },
4275 {
4276 "path": "../classic/classic/src/form/action/DirectAction.js",
4277 "requires": [
4278 0
4279 ],
4280 "uses": [
4281 210
4282 ],
4283 "idx": 436
4284 },
4285 {
4286 "path": "../classic/classic/src/form/action/DirectLoad.js",
4287 "requires": [
4288 210,
4289 409,
4290 436
4291 ],
4292 "uses": [],
4293 "idx": 437
4294 },
4295 {
4296 "path": "../classic/classic/src/form/action/DirectSubmit.js",
4297 "requires": [
4298 210,
4299 410,
4300 436
4301 ],
4302 "uses": [],
4303 "idx": 438
4304 },
4305 {
4306 "path": "../classic/classic/src/form/action/StandardSubmit.js",
4307 "requires": [
4308 410
4309 ],
4310 "uses": [],
4311 "idx": 439
4312 },
4313 {
4314 "path": "../classic/classic/src/form/field/Picker.js",
4315 "requires": [
4316 358,
4317 419
4318 ],
4319 "uses": [],
4320 "idx": 440
4321 },
4322 {
4323 "path": "../classic/classic/src/selection/Model.js",
4324 "requires": [
4325 4,
4326 12,
4327 339
4328 ],
4329 "uses": [
4330 127
4331 ],
4332 "idx": 441
4333 },
4334 {
4335 "path": "../classic/classic/src/selection/DataViewModel.js",
4336 "requires": [
4337 358,
4338 441
4339 ],
4340 "uses": [],
4341 "idx": 442
4342 },
4343 {
4344 "path": "../classic/classic/src/view/NavigationModel.js",
4345 "requires": [
4346 12,
4347 51,
4348 339
4349 ],
4350 "uses": [
4351 358
4352 ],
4353 "idx": 443
4354 },
4355 {
4356 "path": "../classic/classic/src/view/AbstractView.js",
4357 "requires": [
4358 75,
4359 119,
4360 339,
4361 340,
4362 442,
4363 443
4364 ],
4365 "uses": [
4366 12,
4367 19,
4368 49,
4369 85,
4370 88,
4371 175,
4372 230,
4373 323
4374 ],
4375 "idx": 444
4376 },
4377 {
4378 "path": "../classic/classic/src/view/View.js",
4379 "requires": [
4380 444
4381 ],
4382 "uses": [],
4383 "idx": 445
4384 },
4385 {
4386 "path": "../classic/classic/src/view/BoundListKeyNav.js",
4387 "requires": [
4388 443
4389 ],
4390 "uses": [
4391 35,
4392 358
4393 ],
4394 "idx": 446
4395 },
4396 {
4397 "path": "../classic/classic/src/layout/component/BoundList.js",
4398 "requires": [
4399 342
4400 ],
4401 "uses": [],
4402 "idx": 447
4403 },
4404 {
4405 "path": "../classic/classic/src/toolbar/Item.js",
4406 "requires": [
4407 119,
4408 368
4409 ],
4410 "uses": [],
4411 "idx": 448
4412 },
4413 {
4414 "path": "../classic/classic/src/toolbar/TextItem.js",
4415 "requires": [
4416 88,
4417 368,
4418 448
4419 ],
4420 "uses": [],
4421 "idx": 449
4422 },
4423 {
4424 "path": "../classic/classic/src/form/trigger/Spinner.js",
4425 "requires": [
4426 418
4427 ],
4428 "uses": [],
4429 "idx": 450
4430 },
4431 {
4432 "path": "../classic/classic/src/form/field/Spinner.js",
4433 "requires": [
4434 358,
4435 419,
4436 450
4437 ],
4438 "uses": [],
4439 "idx": 451
4440 },
4441 {
4442 "path": "../classic/classic/src/form/field/Number.js",
4443 "requires": [
4444 451
4445 ],
4446 "uses": [
4447 84,
4448 85
4449 ],
4450 "idx": 452
4451 },
4452 {
4453 "path": "../classic/classic/src/toolbar/Paging.js",
4454 "requires": [
4455 339,
4456 368,
4457 449,
4458 452
4459 ],
4460 "uses": [
4461 85,
4462 195,
4463 342,
4464 450
4465 ],
4466 "idx": 453
4467 },
4468 {
4469 "path": "../classic/classic/src/view/BoundList.js",
4470 "requires": [
4471 49,
4472 223,
4473 445,
4474 446,
4475 447,
4476 453
4477 ],
4478 "uses": [
4479 88,
4480 195,
4481 342,
4482 471
4483 ],
4484 "idx": 454
4485 },
4486 {
4487 "path": "../classic/classic/src/form/field/ComboBox.js",
4488 "requires": [
4489 1,
4490 175,
4491 339,
4492 440,
4493 454
4494 ],
4495 "uses": [
4496 35,
4497 49,
4498 50,
4499 88,
4500 127,
4501 155,
4502 170,
4503 195,
4504 230,
4505 442,
4506 446,
4507 447
4508 ],
4509 "idx": 455
4510 },
4511 {
4512 "path": "../classic/classic/src/picker/Month.js",
4513 "requires": [
4514 88,
4515 119,
4516 348,
4517 349
4518 ],
4519 "uses": [
4520 195,
4521 342
4522 ],
4523 "idx": 456
4524 },
4525 {
4526 "path": "../classic/classic/src/picker/Date.js",
4527 "requires": [
4528 66,
4529 88,
4530 119,
4531 348,
4532 349,
4533 350,
4534 358,
4535 456
4536 ],
4537 "uses": [
4538 85,
4539 195,
4540 230,
4541 342
4542 ],
4543 "idx": 457
4544 },
4545 {
4546 "path": "../classic/classic/src/form/field/Date.js",
4547 "requires": [
4548 440,
4549 457
4550 ],
4551 "uses": [
4552 85,
4553 195,
4554 342
4555 ],
4556 "idx": 458
4557 },
4558 {
4559 "path": "../classic/classic/src/form/field/Display.js",
4560 "requires": [
4561 84,
4562 88,
4563 416
4564 ],
4565 "uses": [],
4566 "idx": 459
4567 },
4568 {
4569 "path": "../classic/classic/src/form/field/FileButton.js",
4570 "requires": [
4571 349
4572 ],
4573 "uses": [],
4574 "idx": 460
4575 },
4576 {
4577 "path": "../classic/classic/src/form/trigger/Component.js",
4578 "requires": [
4579 418
4580 ],
4581 "uses": [],
4582 "idx": 461
4583 },
4584 {
4585 "path": "../classic/classic/src/form/field/File.js",
4586 "requires": [
4587 419,
4588 460,
4589 461
4590 ],
4591 "uses": [
4592 195,
4593 342
4594 ],
4595 "idx": 462
4596 },
4597 {
4598 "path": "../classic/classic/src/form/field/Hidden.js",
4599 "requires": [
4600 416
4601 ],
4602 "uses": [],
4603 "idx": 463
4604 },
4605 {
4606 "path": "../classic/classic/src/tip/Tip.js",
4607 "requires": [
4608 379
4609 ],
4610 "uses": [
4611 119
4612 ],
4613 "idx": 464
4614 },
4615 {
4616 "path": "../classic/classic/src/tip/ToolTip.js",
4617 "requires": [
4618 464
4619 ],
4620 "uses": [
4621 49
4622 ],
4623 "idx": 465
4624 },
4625 {
4626 "path": "../classic/classic/src/tip/QuickTip.js",
4627 "requires": [
4628 465
4629 ],
4630 "uses": [],
4631 "idx": 466
4632 },
4633 {
4634 "path": "../classic/classic/src/tip/QuickTipManager.js",
4635 "requires": [
4636 466
4637 ],
4638 "uses": [],
4639 "idx": 467
4640 },
4641 {
4642 "path": "../classic/classic/src/picker/Color.js",
4643 "requires": [
4644 88,
4645 119
4646 ],
4647 "uses": [],
4648 "idx": 468
4649 },
4650 {
4651 "path": "../classic/classic/src/layout/component/field/HtmlEditor.js",
4652 "requires": [
4653 424
4654 ],
4655 "uses": [],
4656 "idx": 469
4657 },
4658 {
4659 "path": "../classic/classic/src/toolbar/Separator.js",
4660 "requires": [
4661 368,
4662 448
4663 ],
4664 "uses": [],
4665 "idx": 470
4666 },
4667 {
4668 "path": "../classic/classic/src/layout/container/boxOverflow/Menu.js",
4669 "requires": [
4670 349,
4671 361,
4672 470
4673 ],
4674 "uses": [
4675 195,
4676 342,
4677 362,
4678 367,
4679 376,
4680 519,
4681 602
4682 ],
4683 "idx": 471
4684 },
4685 {
4686 "path": "../classic/classic/src/form/field/HtmlEditor.js",
4687 "requires": [
4688 84,
4689 323,
4690 367,
4691 368,
4692 415,
4693 425,
4694 448,
4695 467,
4696 468,
4697 469,
4698 471
4699 ],
4700 "uses": [
4701 1,
4702 85,
4703 119,
4704 195,
4705 230,
4706 342,
4707 362,
4708 376,
4709 519
4710 ],
4711 "idx": 472
4712 },
4713 {
4714 "path": "../classic/classic/src/form/field/Tag.js",
4715 "requires": [
4716 172,
4717 207,
4718 441,
4719 455
4720 ],
4721 "uses": [
4722 50,
4723 88
4724 ],
4725 "idx": 473
4726 },
4727 {
4728 "path": "../classic/classic/src/picker/Time.js",
4729 "requires": [
4730 172,
4731 454
4732 ],
4733 "uses": [
4734 50
4735 ],
4736 "idx": 474
4737 },
4738 {
4739 "path": "../classic/classic/src/form/field/Time.js",
4740 "requires": [
4741 446,
4742 455,
4743 458,
4744 474
4745 ],
4746 "uses": [
4747 85,
4748 88,
4749 195,
4750 442,
4751 447
4752 ],
4753 "idx": 475
4754 },
4755 {
4756 "path": "../classic/classic/src/form/field/Trigger.js",
4757 "requires": [
4758 230,
4759 348,
4760 419
4761 ],
4762 "uses": [],
4763 "idx": 476
4764 },
4765 {
4766 "path": "../classic/classic/src/grid/CellContext.js",
4767 "requires": [],
4768 "uses": [],
4769 "idx": 477
4770 },
4771 {
4772 "path": "../classic/classic/src/grid/CellEditor.js",
4773 "requires": [
4774 336
4775 ],
4776 "uses": [],
4777 "idx": 478
4778 },
4779 {
4780 "path": "../classic/classic/src/grid/ColumnComponentLayout.js",
4781 "requires": [
4782 342
4783 ],
4784 "uses": [],
4785 "idx": 479
4786 },
4787 {
4788 "path": "../classic/classic/src/layout/container/Fit.js",
4789 "requires": [
4790 331
4791 ],
4792 "uses": [],
4793 "idx": 480
4794 },
4795 {
4796 "path": "../classic/classic/src/panel/Table.js",
4797 "requires": [
4798 379,
4799 480
4800 ],
4801 "uses": [
4802 1,
4803 175,
4804 230,
4805 484,
4806 499,
4807 531,
4808 532,
4809 573,
4810 574,
4811 575
4812 ],
4813 "idx": 481
4814 },
4815 {
4816 "path": "../classic/classic/src/grid/ColumnLayout.js",
4817 "requires": [
4818 366,
4819 481
4820 ],
4821 "uses": [],
4822 "idx": 482
4823 },
4824 {
4825 "path": "../classic/classic/src/grid/ColumnManager.js",
4826 "requires": [],
4827 "uses": [],
4828 "idx": 483
4829 },
4830 {
4831 "path": "../classic/classic/src/grid/NavigationModel.js",
4832 "requires": [
4833 443
4834 ],
4835 "uses": [
4836 20,
4837 35,
4838 74,
4839 119,
4840 358,
4841 477
4842 ],
4843 "idx": 484
4844 },
4845 {
4846 "path": "../classic/classic/src/view/TableLayout.js",
4847 "requires": [
4848 342
4849 ],
4850 "uses": [],
4851 "idx": 485
4852 },
4853 {
4854 "path": "../classic/classic/src/grid/locking/RowSynchronizer.js",
4855 "requires": [],
4856 "uses": [],
4857 "idx": 486
4858 },
4859 {
4860 "path": "../classic/classic/src/view/NodeCache.js",
4861 "requires": [
4862 75
4863 ],
4864 "uses": [
4865 49,
4866 74
4867 ],
4868 "idx": 487
4869 },
4870 {
4871 "path": "../classic/classic/src/view/Table.js",
4872 "requires": [
4873 1,
4874 55,
4875 445,
4876 477,
4877 485,
4878 486,
4879 487
4880 ],
4881 "uses": [
4882 12,
4883 49,
4884 74,
4885 88,
4886 119,
4887 155,
4888 499
4889 ],
4890 "idx": 488
4891 },
4892 {
4893 "path": "../classic/classic/src/grid/Panel.js",
4894 "requires": [
4895 481,
4896 488
4897 ],
4898 "uses": [],
4899 "idx": 489
4900 },
4901 {
4902 "path": "../classic/classic/src/grid/RowEditorButtons.js",
4903 "requires": [
4904 334
4905 ],
4906 "uses": [
4907 195,
4908 342,
4909 349,
4910 379
4911 ],
4912 "idx": 490
4913 },
4914 {
4915 "path": "../classic/classic/src/grid/RowEditor.js",
4916 "requires": [
4917 358,
4918 432,
4919 465,
4920 490
4921 ],
4922 "uses": [
4923 49,
4924 76,
4925 195,
4926 332,
4927 334,
4928 342,
4929 376,
4930 459,
4931 477
4932 ],
4933 "idx": 491
4934 },
4935 {
4936 "path": "../classic/classic/src/grid/Scroller.js",
4937 "requires": [],
4938 "uses": [],
4939 "idx": 492
4940 },
4941 {
4942 "path": "../classic/classic/src/view/DropZone.js",
4943 "requires": [
4944 403
4945 ],
4946 "uses": [
4947 119,
4948 195,
4949 342
4950 ],
4951 "idx": 493
4952 },
4953 {
4954 "path": "../classic/classic/src/grid/ViewDropZone.js",
4955 "requires": [
4956 493
4957 ],
4958 "uses": [],
4959 "idx": 494
4960 },
4961 {
4962 "path": "../classic/classic/src/grid/plugin/HeaderResizer.js",
4963 "requires": [
4964 33,
4965 315,
4966 390
4967 ],
4968 "uses": [
4969 500
4970 ],
4971 "idx": 495
4972 },
4973 {
4974 "path": "../classic/classic/src/grid/header/DragZone.js",
4975 "requires": [
4976 401
4977 ],
4978 "uses": [],
4979 "idx": 496
4980 },
4981 {
4982 "path": "../classic/classic/src/grid/header/DropZone.js",
4983 "requires": [
4984 403
4985 ],
4986 "uses": [
4987 363
4988 ],
4989 "idx": 497
4990 },
4991 {
4992 "path": "../classic/classic/src/grid/plugin/HeaderReorderer.js",
4993 "requires": [
4994 315,
4995 496,
4996 497
4997 ],
4998 "uses": [],
4999 "idx": 498
5000 },
5001 {
5002 "path": "../classic/classic/src/grid/header/Container.js",
5003 "requires": [
5004 334,
5005 358,
5006 359,
5007 482,
5008 495,
5009 498
5010 ],
5011 "uses": [
5012 1,
5013 119,
5014 195,
5015 342,
5016 362,
5017 367,
5018 376,
5019 483,
5020 500,
5021 517,
5022 518,
5023 519
5024 ],
5025 "idx": 499
5026 },
5027 {
5028 "path": "../classic/classic/src/grid/column/Column.js",
5029 "requires": [
5030 205,
5031 479,
5032 482,
5033 499
5034 ],
5035 "uses": [
5036 84,
5037 495
5038 ],
5039 "idx": 500
5040 },
5041 {
5042 "path": "../classic/classic/src/grid/column/Action.js",
5043 "requires": [
5044 500
5045 ],
5046 "uses": [
5047 49
5048 ],
5049 "idx": 501
5050 },
5051 {
5052 "path": "../classic/classic/src/grid/column/Boolean.js",
5053 "requires": [
5054 500
5055 ],
5056 "uses": [],
5057 "idx": 502
5058 },
5059 {
5060 "path": "../classic/classic/src/grid/column/Check.js",
5061 "requires": [
5062 500
5063 ],
5064 "uses": [],
5065 "idx": 503
5066 },
5067 {
5068 "path": "../classic/classic/src/grid/column/Date.js",
5069 "requires": [
5070 500
5071 ],
5072 "uses": [
5073 84
5074 ],
5075 "idx": 504
5076 },
5077 {
5078 "path": "../classic/classic/src/grid/column/Number.js",
5079 "requires": [
5080 84,
5081 500
5082 ],
5083 "uses": [],
5084 "idx": 505
5085 },
5086 {
5087 "path": "../classic/classic/src/grid/column/RowNumberer.js",
5088 "requires": [
5089 500
5090 ],
5091 "uses": [],
5092 "idx": 506
5093 },
5094 {
5095 "path": "../classic/classic/src/grid/column/Template.js",
5096 "requires": [
5097 88,
5098 500
5099 ],
5100 "uses": [
5101 503
5102 ],
5103 "idx": 507
5104 },
5105 {
5106 "path": "../classic/classic/src/grid/column/Widget.js",
5107 "requires": [
5108 500
5109 ],
5110 "uses": [],
5111 "idx": 508
5112 },
5113 {
5114 "path": "../classic/classic/src/grid/feature/Feature.js",
5115 "requires": [
5116 51
5117 ],
5118 "uses": [],
5119 "idx": 509
5120 },
5121 {
5122 "path": "../classic/classic/src/grid/feature/AbstractSummary.js",
5123 "requires": [
5124 509
5125 ],
5126 "uses": [],
5127 "idx": 510
5128 },
5129 {
5130 "path": "../classic/classic/src/grid/feature/GroupStore.js",
5131 "requires": [
5132 51
5133 ],
5134 "uses": [
5135 127
5136 ],
5137 "idx": 511
5138 },
5139 {
5140 "path": "../classic/classic/src/grid/feature/Grouping.js",
5141 "requires": [
5142 509,
5143 510,
5144 511
5145 ],
5146 "uses": [
5147 88,
5148 155,
5149 499
5150 ],
5151 "idx": 512
5152 },
5153 {
5154 "path": "../classic/classic/src/grid/feature/GroupingSummary.js",
5155 "requires": [
5156 512
5157 ],
5158 "uses": [],
5159 "idx": 513
5160 },
5161 {
5162 "path": "../classic/classic/src/grid/feature/RowBody.js",
5163 "requires": [
5164 509
5165 ],
5166 "uses": [
5167 88
5168 ],
5169 "idx": 514
5170 },
5171 {
5172 "path": "../classic/classic/src/grid/feature/Summary.js",
5173 "requires": [
5174 510
5175 ],
5176 "uses": [
5177 88,
5178 119,
5179 155,
5180 195,
5181 342
5182 ],
5183 "idx": 515
5184 },
5185 {
5186 "path": "../classic/classic/src/menu/Item.js",
5187 "requires": [
5188 119,
5189 223
5190 ],
5191 "uses": [
5192 347,
5193 467
5194 ],
5195 "idx": 516
5196 },
5197 {
5198 "path": "../classic/classic/src/menu/CheckItem.js",
5199 "requires": [
5200 516
5201 ],
5202 "uses": [
5203 347
5204 ],
5205 "idx": 517
5206 },
5207 {
5208 "path": "../classic/classic/src/menu/Separator.js",
5209 "requires": [
5210 516
5211 ],
5212 "uses": [],
5213 "idx": 518
5214 },
5215 {
5216 "path": "../classic/classic/src/menu/Menu.js",
5217 "requires": [
5218 347,
5219 359,
5220 367,
5221 379,
5222 516,
5223 517,
5224 518
5225 ],
5226 "uses": [
5227 20,
5228 35,
5229 49,
5230 195,
5231 342,
5232 358
5233 ],
5234 "idx": 519
5235 },
5236 {
5237 "path": "../classic/classic/src/grid/filters/filter/Base.js",
5238 "requires": [
5239 12,
5240 195,
5241 362,
5242 367,
5243 376,
5244 519
5245 ],
5246 "uses": [
5247 1,
5248 50
5249 ],
5250 "idx": 520
5251 },
5252 {
5253 "path": "../classic/classic/src/grid/filters/filter/SingleFilter.js",
5254 "requires": [
5255 520
5256 ],
5257 "uses": [],
5258 "idx": 521
5259 },
5260 {
5261 "path": "../classic/classic/src/grid/filters/filter/Boolean.js",
5262 "requires": [
5263 521
5264 ],
5265 "uses": [],
5266 "idx": 522
5267 },
5268 {
5269 "path": "../classic/classic/src/grid/filters/filter/TriFilter.js",
5270 "requires": [
5271 520
5272 ],
5273 "uses": [],
5274 "idx": 523
5275 },
5276 {
5277 "path": "../classic/classic/src/grid/filters/filter/Date.js",
5278 "requires": [
5279 195,
5280 342,
5281 517,
5282 523
5283 ],
5284 "uses": [
5285 362,
5286 367,
5287 376,
5288 457,
5289 566
5290 ],
5291 "idx": 524
5292 },
5293 {
5294 "path": "../classic/classic/src/grid/filters/filter/List.js",
5295 "requires": [
5296 521
5297 ],
5298 "uses": [
5299 172,
5300 175
5301 ],
5302 "idx": 525
5303 },
5304 {
5305 "path": "../classic/classic/src/grid/filters/filter/Number.js",
5306 "requires": [
5307 195,
5308 342,
5309 450,
5310 523
5311 ],
5312 "uses": [
5313 452
5314 ],
5315 "idx": 526
5316 },
5317 {
5318 "path": "../classic/classic/src/grid/filters/filter/String.js",
5319 "requires": [
5320 195,
5321 342,
5322 419,
5323 521
5324 ],
5325 "uses": [],
5326 "idx": 527
5327 },
5328 {
5329 "path": "../classic/classic/src/grid/filters/Filters.js",
5330 "requires": [
5331 315,
5332 339,
5333 520,
5334 521,
5335 522,
5336 523,
5337 524,
5338 525,
5339 526,
5340 527
5341 ],
5342 "uses": [
5343 12
5344 ],
5345 "idx": 528
5346 },
5347 {
5348 "path": "../classic/classic/src/grid/locking/HeaderContainer.js",
5349 "requires": [
5350 483,
5351 499
5352 ],
5353 "uses": [],
5354 "idx": 529
5355 },
5356 {
5357 "path": "../classic/classic/src/grid/locking/View.js",
5358 "requires": [
5359 51,
5360 116,
5361 119,
5362 339,
5363 444,
5364 488
5365 ],
5366 "uses": [
5367 340,
5368 477
5369 ],
5370 "idx": 530
5371 },
5372 {
5373 "path": "../classic/classic/src/grid/locking/Lockable.js",
5374 "requires": [
5375 119,
5376 488,
5377 499,
5378 529,
5379 530
5380 ],
5381 "uses": [
5382 1,
5383 175,
5384 195,
5385 332,
5386 342,
5387 364,
5388 365
5389 ],
5390 "idx": 531
5391 },
5392 {
5393 "path": "../classic/classic/src/grid/plugin/BufferedRenderer.js",
5394 "requires": [
5395 315
5396 ],
5397 "uses": [
5398 1,
5399 49,
5400 486
5401 ],
5402 "idx": 532
5403 },
5404 {
5405 "path": "../classic/classic/src/grid/plugin/Editing.js",
5406 "requires": [
5407 4,
5408 315,
5409 358,
5410 416,
5411 488,
5412 500
5413 ],
5414 "uses": [
5415 20,
5416 195,
5417 342,
5418 477
5419 ],
5420 "idx": 533
5421 },
5422 {
5423 "path": "../classic/classic/src/grid/plugin/CellEditing.js",
5424 "requires": [
5425 1,
5426 478,
5427 533
5428 ],
5429 "uses": [
5430 55,
5431 195,
5432 335,
5433 342,
5434 477
5435 ],
5436 "idx": 534
5437 },
5438 {
5439 "path": "../classic/classic/src/plugin/AbstractClipboard.js",
5440 "requires": [
5441 315,
5442 357
5443 ],
5444 "uses": [
5445 49
5446 ],
5447 "idx": 535
5448 },
5449 {
5450 "path": "../classic/classic/src/grid/plugin/Clipboard.js",
5451 "requires": [
5452 84,
5453 322,
5454 535
5455 ],
5456 "uses": [
5457 477
5458 ],
5459 "idx": 536
5460 },
5461 {
5462 "path": "../classic/classic/src/grid/plugin/DragDrop.js",
5463 "requires": [
5464 315
5465 ],
5466 "uses": [
5467 494,
5468 608
5469 ],
5470 "idx": 537
5471 },
5472 {
5473 "path": "../classic/classic/src/grid/plugin/RowEditing.js",
5474 "requires": [
5475 491,
5476 533
5477 ],
5478 "uses": [],
5479 "idx": 538
5480 },
5481 {
5482 "path": "../classic/classic/src/grid/plugin/RowExpander.js",
5483 "requires": [
5484 315,
5485 514
5486 ],
5487 "uses": [
5488 88,
5489 500
5490 ],
5491 "idx": 539
5492 },
5493 {
5494 "path": "../classic/classic/src/grid/property/Grid.js",
5495 "requires": [
5496 489
5497 ],
5498 "uses": [
5499 20,
5500 88,
5501 155,
5502 195,
5503 335,
5504 342,
5505 416,
5506 419,
5507 450,
5508 452,
5509 455,
5510 458,
5511 478,
5512 488,
5513 534,
5514 541,
5515 544
5516 ],
5517 "idx": 540
5518 },
5519 {
5520 "path": "../classic/classic/src/grid/property/HeaderContainer.js",
5521 "requires": [
5522 84,
5523 499
5524 ],
5525 "uses": [],
5526 "idx": 541
5527 },
5528 {
5529 "path": "../classic/classic/src/grid/property/Property.js",
5530 "requires": [
5531 155
5532 ],
5533 "uses": [],
5534 "idx": 542
5535 },
5536 {
5537 "path": "../classic/classic/src/grid/property/Reader.js",
5538 "requires": [
5539 157
5540 ],
5541 "uses": [
5542 156
5543 ],
5544 "idx": 543
5545 },
5546 {
5547 "path": "../classic/classic/src/grid/property/Store.js",
5548 "requires": [
5549 161,
5550 172,
5551 542,
5552 543
5553 ],
5554 "uses": [
5555 167
5556 ],
5557 "idx": 544
5558 },
5559 {
5560 "path": "../classic/classic/src/grid/selection/Selection.js",
5561 "requires": [],
5562 "uses": [],
5563 "idx": 545
5564 },
5565 {
5566 "path": "../classic/classic/src/grid/selection/Cells.js",
5567 "requires": [
5568 545
5569 ],
5570 "uses": [
5571 477
5572 ],
5573 "idx": 546
5574 },
5575 {
5576 "path": "../classic/classic/src/grid/selection/Columns.js",
5577 "requires": [
5578 545
5579 ],
5580 "uses": [
5581 477
5582 ],
5583 "idx": 547
5584 },
5585 {
5586 "path": "../classic/classic/src/grid/selection/Replicator.js",
5587 "requires": [
5588 315
5589 ],
5590 "uses": [],
5591 "idx": 548
5592 },
5593 {
5594 "path": "../classic/classic/src/grid/selection/Rows.js",
5595 "requires": [
5596 127,
5597 545
5598 ],
5599 "uses": [
5600 477
5601 ],
5602 "idx": 549
5603 },
5604 {
5605 "path": "../classic/classic/src/grid/selection/SelectionExtender.js",
5606 "requires": [
5607 390
5608 ],
5609 "uses": [
5610 49,
5611 323
5612 ],
5613 "idx": 550
5614 },
5615 {
5616 "path": "../classic/classic/src/grid/selection/SpreadsheetModel.js",
5617 "requires": [
5618 441,
5619 506,
5620 545,
5621 546,
5622 547,
5623 549,
5624 550
5625 ],
5626 "uses": [
5627 195,
5628 332,
5629 396,
5630 477,
5631 479
5632 ],
5633 "idx": 551
5634 },
5635 {
5636 "path": "../classic/classic/src/util/Queue.js",
5637 "requires": [],
5638 "uses": [],
5639 "idx": 552
5640 },
5641 {
5642 "path": "../classic/classic/src/layout/ContextItem.js",
5643 "requires": [],
5644 "uses": [
5645 55,
5646 66,
5647 72,
5648 329
5649 ],
5650 "idx": 553
5651 },
5652 {
5653 "path": "../classic/classic/src/layout/Context.js",
5654 "requires": [
5655 66,
5656 72,
5657 314,
5658 330,
5659 552,
5660 553
5661 ],
5662 "uses": [],
5663 "idx": 554
5664 },
5665 {
5666 "path": "../classic/classic/src/layout/SizePolicy.js",
5667 "requires": [],
5668 "uses": [],
5669 "idx": 555
5670 },
5671 {
5672 "path": "../classic/classic/src/layout/component/Body.js",
5673 "requires": [
5674 342
5675 ],
5676 "uses": [],
5677 "idx": 556
5678 },
5679 {
5680 "path": "../classic/classic/src/layout/component/FieldSet.js",
5681 "requires": [
5682 556
5683 ],
5684 "uses": [],
5685 "idx": 557
5686 },
5687 {
5688 "path": "../classic/classic/src/layout/container/Absolute.js",
5689 "requires": [
5690 386
5691 ],
5692 "uses": [],
5693 "idx": 558
5694 },
5695 {
5696 "path": "../classic/classic/src/layout/container/Accordion.js",
5697 "requires": [
5698 367
5699 ],
5700 "uses": [],
5701 "idx": 559
5702 },
5703 {
5704 "path": "../classic/classic/src/resizer/BorderSplitter.js",
5705 "requires": [
5706 364
5707 ],
5708 "uses": [
5709 569
5710 ],
5711 "idx": 560
5712 },
5713 {
5714 "path": "../classic/classic/src/layout/container/Border.js",
5715 "requires": [
5716 72,
5717 120,
5718 331,
5719 560
5720 ],
5721 "uses": [
5722 84,
5723 195,
5724 342
5725 ],
5726 "idx": 561
5727 },
5728 {
5729 "path": "../classic/classic/src/layout/container/Card.js",
5730 "requires": [
5731 480
5732 ],
5733 "uses": [
5734 49
5735 ],
5736 "idx": 562
5737 },
5738 {
5739 "path": "../classic/classic/src/layout/container/Center.js",
5740 "requires": [
5741 480
5742 ],
5743 "uses": [],
5744 "idx": 563
5745 },
5746 {
5747 "path": "../classic/classic/src/layout/container/Form.js",
5748 "requires": [
5749 332
5750 ],
5751 "uses": [],
5752 "idx": 564
5753 },
5754 {
5755 "path": "../classic/classic/src/menu/ColorPicker.js",
5756 "requires": [
5757 468,
5758 519
5759 ],
5760 "uses": [
5761 195,
5762 342,
5763 347
5764 ],
5765 "idx": 565
5766 },
5767 {
5768 "path": "../classic/classic/src/menu/DatePicker.js",
5769 "requires": [
5770 457,
5771 519
5772 ],
5773 "uses": [
5774 195,
5775 342,
5776 347
5777 ],
5778 "idx": 566
5779 },
5780 {
5781 "path": "../classic/classic/src/panel/Pinnable.js",
5782 "requires": [
5783 0
5784 ],
5785 "uses": [
5786 195,
5787 342,
5788 356
5789 ],
5790 "idx": 567
5791 },
5792 {
5793 "path": "../classic/classic/src/plugin/Manager.js",
5794 "requires": [],
5795 "uses": [],
5796 "idx": 568
5797 },
5798 {
5799 "path": "../classic/classic/src/resizer/BorderSplitterTracker.js",
5800 "requires": [
5801 33,
5802 391
5803 ],
5804 "uses": [],
5805 "idx": 569
5806 },
5807 {
5808 "path": "../classic/classic/src/resizer/Handle.js",
5809 "requires": [
5810 119
5811 ],
5812 "uses": [],
5813 "idx": 570
5814 },
5815 {
5816 "path": "../classic/classic/src/resizer/ResizeTracker.js",
5817 "requires": [
5818 390
5819 ],
5820 "uses": [],
5821 "idx": 571
5822 },
5823 {
5824 "path": "../classic/classic/src/resizer/Resizer.js",
5825 "requires": [
5826 51
5827 ],
5828 "uses": [
5829 49,
5830 85,
5831 119,
5832 230,
5833 571
5834 ],
5835 "idx": 572
5836 },
5837 {
5838 "path": "../classic/classic/src/selection/CellModel.js",
5839 "requires": [
5840 442,
5841 477
5842 ],
5843 "uses": [],
5844 "idx": 573
5845 },
5846 {
5847 "path": "../classic/classic/src/selection/RowModel.js",
5848 "requires": [
5849 442,
5850 477
5851 ],
5852 "uses": [],
5853 "idx": 574
5854 },
5855 {
5856 "path": "../classic/classic/src/selection/CheckboxModel.js",
5857 "requires": [
5858 574
5859 ],
5860 "uses": [
5861 195,
5862 332,
5863 477,
5864 479,
5865 500
5866 ],
5867 "idx": 575
5868 },
5869 {
5870 "path": "../classic/classic/src/selection/TreeModel.js",
5871 "requires": [
5872 574
5873 ],
5874 "uses": [],
5875 "idx": 576
5876 },
5877 {
5878 "path": "../classic/classic/src/slider/Thumb.js",
5879 "requires": [
5880 84,
5881 390
5882 ],
5883 "uses": [
5884 72
5885 ],
5886 "idx": 577
5887 },
5888 {
5889 "path": "../classic/classic/src/slider/Tip.js",
5890 "requires": [
5891 464
5892 ],
5893 "uses": [],
5894 "idx": 578
5895 },
5896 {
5897 "path": "../classic/classic/src/slider/Multi.js",
5898 "requires": [
5899 84,
5900 85,
5901 416,
5902 577,
5903 578
5904 ],
5905 "uses": [
5906 230
5907 ],
5908 "idx": 579
5909 },
5910 {
5911 "path": "../classic/classic/src/slider/Single.js",
5912 "requires": [
5913 579
5914 ],
5915 "uses": [],
5916 "idx": 580
5917 },
5918 {
5919 "path": "../classic/classic/src/slider/Widget.js",
5920 "requires": [
5921 81,
5922 579
5923 ],
5924 "uses": [
5925 72,
5926 84
5927 ],
5928 "idx": 581
5929 },
5930 {
5931 "path": "../classic/classic/src/sparkline/Shape.js",
5932 "requires": [],
5933 "uses": [],
5934 "idx": 582
5935 },
5936 {
5937 "path": "../classic/classic/src/sparkline/CanvasBase.js",
5938 "requires": [
5939 582
5940 ],
5941 "uses": [],
5942 "idx": 583
5943 },
5944 {
5945 "path": "../classic/classic/src/sparkline/CanvasCanvas.js",
5946 "requires": [
5947 583
5948 ],
5949 "uses": [],
5950 "idx": 584
5951 },
5952 {
5953 "path": "../classic/classic/src/sparkline/VmlCanvas.js",
5954 "requires": [
5955 583
5956 ],
5957 "uses": [],
5958 "idx": 585
5959 },
5960 {
5961 "path": "../classic/classic/src/sparkline/Base.js",
5962 "requires": [
5963 81,
5964 88,
5965 195,
5966 332,
5967 376,
5968 465,
5969 584,
5970 585
5971 ],
5972 "uses": [],
5973 "idx": 586
5974 },
5975 {
5976 "path": "../classic/classic/src/sparkline/BarBase.js",
5977 "requires": [
5978 586
5979 ],
5980 "uses": [],
5981 "idx": 587
5982 },
5983 {
5984 "path": "../classic/classic/src/sparkline/RangeMap.js",
5985 "requires": [],
5986 "uses": [],
5987 "idx": 588
5988 },
5989 {
5990 "path": "../classic/classic/src/sparkline/Bar.js",
5991 "requires": [
5992 88,
5993 587,
5994 588
5995 ],
5996 "uses": [],
5997 "idx": 589
5998 },
5999 {
6000 "path": "../classic/classic/src/sparkline/Box.js",
6001 "requires": [
6002 88,
6003 586
6004 ],
6005 "uses": [],
6006 "idx": 590
6007 },
6008 {
6009 "path": "../classic/classic/src/sparkline/Bullet.js",
6010 "requires": [
6011 88,
6012 586
6013 ],
6014 "uses": [],
6015 "idx": 591
6016 },
6017 {
6018 "path": "../classic/classic/src/sparkline/Discrete.js",
6019 "requires": [
6020 88,
6021 587
6022 ],
6023 "uses": [],
6024 "idx": 592
6025 },
6026 {
6027 "path": "../classic/classic/src/sparkline/Line.js",
6028 "requires": [
6029 88,
6030 586,
6031 588
6032 ],
6033 "uses": [],
6034 "idx": 593
6035 },
6036 {
6037 "path": "../classic/classic/src/sparkline/Pie.js",
6038 "requires": [
6039 88,
6040 586
6041 ],
6042 "uses": [],
6043 "idx": 594
6044 },
6045 {
6046 "path": "../classic/classic/src/sparkline/TriState.js",
6047 "requires": [
6048 88,
6049 587,
6050 588
6051 ],
6052 "uses": [],
6053 "idx": 595
6054 },
6055 {
6056 "path": "../classic/classic/src/state/CookieProvider.js",
6057 "requires": [
6058 113
6059 ],
6060 "uses": [],
6061 "idx": 596
6062 },
6063 {
6064 "path": "../classic/classic/src/state/LocalStorageProvider.js",
6065 "requires": [
6066 113,
6067 321
6068 ],
6069 "uses": [],
6070 "idx": 597
6071 },
6072 {
6073 "path": "../classic/classic/src/tab/Tab.js",
6074 "requires": [
6075 349
6076 ],
6077 "uses": [],
6078 "idx": 598
6079 },
6080 {
6081 "path": "../classic/classic/src/tab/Bar.js",
6082 "requires": [
6083 34,
6084 354,
6085 359,
6086 556,
6087 598
6088 ],
6089 "uses": [
6090 33
6091 ],
6092 "idx": 599
6093 },
6094 {
6095 "path": "../classic/classic/src/tab/Panel.js",
6096 "requires": [
6097 379,
6098 562,
6099 599
6100 ],
6101 "uses": [
6102 195,
6103 342,
6104 598
6105 ],
6106 "idx": 600
6107 },
6108 {
6109 "path": "../classic/classic/src/toolbar/Breadcrumb.js",
6110 "requires": [
6111 227,
6112 334,
6113 350,
6114 359
6115 ],
6116 "uses": [
6117 175
6118 ],
6119 "idx": 601
6120 },
6121 {
6122 "path": "../classic/classic/src/toolbar/Fill.js",
6123 "requires": [
6124 119,
6125 368
6126 ],
6127 "uses": [],
6128 "idx": 602
6129 },
6130 {
6131 "path": "../classic/classic/src/toolbar/Spacer.js",
6132 "requires": [
6133 119,
6134 368
6135 ],
6136 "uses": [],
6137 "idx": 603
6138 },
6139 {
6140 "path": "../classic/classic/src/tree/Column.js",
6141 "requires": [
6142 500
6143 ],
6144 "uses": [],
6145 "idx": 604
6146 },
6147 {
6148 "path": "../classic/classic/src/tree/NavigationModel.js",
6149 "requires": [
6150 484
6151 ],
6152 "uses": [
6153 35
6154 ],
6155 "idx": 605
6156 },
6157 {
6158 "path": "../classic/classic/src/tree/View.js",
6159 "requires": [
6160 488
6161 ],
6162 "uses": [
6163 49,
6164 88
6165 ],
6166 "idx": 606
6167 },
6168 {
6169 "path": "../classic/classic/src/tree/Panel.js",
6170 "requires": [
6171 227,
6172 481,
6173 576,
6174 604,
6175 605,
6176 606
6177 ],
6178 "uses": [
6179 175,
6180 195,
6181 332,
6182 479
6183 ],
6184 "idx": 607
6185 },
6186 {
6187 "path": "../classic/classic/src/view/DragZone.js",
6188 "requires": [
6189 401
6190 ],
6191 "uses": [
6192 85
6193 ],
6194 "idx": 608
6195 },
6196 {
6197 "path": "../classic/classic/src/tree/ViewDragZone.js",
6198 "requires": [
6199 608
6200 ],
6201 "uses": [
6202 85
6203 ],
6204 "idx": 609
6205 },
6206 {
6207 "path": "../classic/classic/src/tree/ViewDropZone.js",
6208 "requires": [
6209 493
6210 ],
6211 "uses": [],
6212 "idx": 610
6213 },
6214 {
6215 "path": "../classic/classic/src/tree/plugin/TreeViewDragDrop.js",
6216 "requires": [
6217 315
6218 ],
6219 "uses": [
6220 609,
6221 610
6222 ],
6223 "idx": 611
6224 },
6225 {
6226 "path": "../classic/classic/src/util/CSS.js",
6227 "requires": [],
6228 "uses": [
6229 49
6230 ],
6231 "idx": 612
6232 },
6233 {
6234 "path": "../classic/classic/src/util/Cookies.js",
6235 "requires": [],
6236 "uses": [],
6237 "idx": 613
6238 },
6239 {
6240 "path": "../classic/classic/src/view/MultiSelectorSearch.js",
6241 "requires": [
6242 379
6243 ],
6244 "uses": [
6245 50,
6246 175,
6247 195,
6248 342,
6249 376,
6250 419,
6251 480,
6252 489
6253 ],
6254 "idx": 614
6255 },
6256 {
6257 "path": "../classic/classic/src/view/MultiSelector.js",
6258 "requires": [
6259 195,
6260 376,
6261 480,
6262 489,
6263 614
6264 ],
6265 "uses": [],
6266 "idx": 615
6267 },
6268 {
6269 "path": "../classic/classic/src/window/Toast.js",
6270 "requires": [
6271 413
6272 ],
6273 "uses": [
6274 1
6275 ],
6276 "idx": 616
6277 }
6278 ],
6279 "classes": {
6280 "Ext.AbstractManager": {
6281 "idx": 6,
6282 "alias": [],
6283 "alternates": []
6284 },
6285 "Ext.Action": {
6286 "idx": 326,
6287 "alias": [],
6288 "alternates": []
6289 },
6290 "Ext.Ajax": {
6291 "idx": 18,
6292 "alias": [],
6293 "alternates": []
6294 },
6295 "Ext.AnimationQueue": {
6296 "idx": 19,
6297 "alias": [],
6298 "alternates": []
6299 },
6300 "Ext.Component": {
6301 "idx": 119,
6302 "alias": [
6303 "widget.box",
6304 "widget.component"
6305 ],
6306 "alternates": [
6307 "Ext.AbstractComponent"
6308 ]
6309 },
6310 "Ext.ComponentLoader": {
6311 "idx": 328,
6312 "alias": [],
6313 "alternates": []
6314 },
6315 "Ext.ComponentManager": {
6316 "idx": 20,
6317 "alias": [],
6318 "alternates": [
6319 "Ext.ComponentMgr"
6320 ]
6321 },
6322 "Ext.ComponentQuery": {
6323 "idx": 23,
6324 "alias": [],
6325 "alternates": []
6326 },
6327 "Ext.Deferred": {
6328 "idx": 11,
6329 "alias": [],
6330 "alternates": []
6331 },
6332 "Ext.Editor": {
6333 "idx": 336,
6334 "alias": [
6335 "widget.editor"
6336 ],
6337 "alternates": []
6338 },
6339 "Ext.ElementLoader": {
6340 "idx": 327,
6341 "alias": [],
6342 "alternates": []
6343 },
6344 "Ext.EventManager": {
6345 "idx": 337,
6346 "alias": [],
6347 "alternates": []
6348 },
6349 "Ext.Evented": {
6350 "idx": 24,
6351 "alias": [],
6352 "alternates": [
6353 "Ext.EventedBase"
6354 ]
6355 },
6356 "Ext.GlobalEvents": {
6357 "idx": 76,
6358 "alias": [],
6359 "alternates": [
6360 "Ext.globalEvents"
6361 ]
6362 },
6363 "Ext.Img": {
6364 "idx": 338,
6365 "alias": [
6366 "widget.image",
6367 "widget.imagecomponent"
6368 ],
6369 "alternates": []
6370 },
6371 "Ext.LoadMask": {
6372 "idx": 340,
6373 "alias": [
6374 "widget.loadmask"
6375 ],
6376 "alternates": []
6377 },
6378 "Ext.Mixin": {
6379 "idx": 0,
6380 "alias": [],
6381 "alternates": []
6382 },
6383 "Ext.Progress": {
6384 "idx": 83,
6385 "alias": [
6386 "widget.progress",
6387 "widget.progressbarwidget"
6388 ],
6389 "alternates": [
6390 "Ext.ProgressBarWidget"
6391 ]
6392 },
6393 "Ext.ProgressBar": {
6394 "idx": 344,
6395 "alias": [
6396 "widget.progressbar"
6397 ],
6398 "alternates": []
6399 },
6400 "Ext.ProgressBase": {
6401 "idx": 82,
6402 "alias": [],
6403 "alternates": []
6404 },
6405 "Ext.Promise": {
6406 "idx": 10,
6407 "alias": [],
6408 "alternates": []
6409 },
6410 "Ext.TaskQueue": {
6411 "idx": 39,
6412 "alias": [],
6413 "alternates": []
6414 },
6415 "Ext.Template": {
6416 "idx": 85,
6417 "alias": [],
6418 "alternates": []
6419 },
6420 "Ext.Widget": {
6421 "idx": 81,
6422 "alias": [
6423 "widget.widget"
6424 ],
6425 "alternates": []
6426 },
6427 "Ext.XTemplate": {
6428 "idx": 88,
6429 "alias": [],
6430 "alternates": []
6431 },
6432 "Ext.ZIndexManager": {
6433 "idx": 333,
6434 "alias": [],
6435 "alternates": [
6436 "Ext.WindowGroup"
6437 ]
6438 },
6439 "Ext.app.Application": {
6440 "idx": 182,
6441 "alias": [],
6442 "alternates": []
6443 },
6444 "Ext.app.BaseController": {
6445 "idx": 123,
6446 "alias": [],
6447 "alternates": []
6448 },
6449 "Ext.app.Controller": {
6450 "idx": 181,
6451 "alias": [],
6452 "alternates": []
6453 },
6454 "Ext.app.EventBus": {
6455 "idx": 121,
6456 "alias": [],
6457 "alternates": []
6458 },
6459 "Ext.app.EventDomain": {
6460 "idx": 89,
6461 "alias": [],
6462 "alternates": []
6463 },
6464 "Ext.app.Profile": {
6465 "idx": 183,
6466 "alias": [],
6467 "alternates": []
6468 },
6469 "Ext.app.Util": {
6470 "idx": 124,
6471 "alias": [],
6472 "alternates": []
6473 },
6474 "Ext.app.ViewController": {
6475 "idx": 185,
6476 "alias": [],
6477 "alternates": []
6478 },
6479 "Ext.app.ViewModel": {
6480 "idx": 208,
6481 "alias": [
6482 "viewmodel.default"
6483 ],
6484 "alternates": []
6485 },
6486 "Ext.app.bind.AbstractStub": {
6487 "idx": 199,
6488 "alias": [],
6489 "alternates": []
6490 },
6491 "Ext.app.bind.BaseBinding": {
6492 "idx": 197,
6493 "alias": [],
6494 "alternates": []
6495 },
6496 "Ext.app.bind.Binding": {
6497 "idx": 198,
6498 "alias": [],
6499 "alternates": []
6500 },
6501 "Ext.app.bind.Formula": {
6502 "idx": 204,
6503 "alias": [],
6504 "alternates": []
6505 },
6506 "Ext.app.bind.LinkStub": {
6507 "idx": 201,
6508 "alias": [],
6509 "alternates": []
6510 },
6511 "Ext.app.bind.Multi": {
6512 "idx": 203,
6513 "alias": [],
6514 "alternates": []
6515 },
6516 "Ext.app.bind.RootStub": {
6517 "idx": 202,
6518 "alias": [],
6519 "alternates": []
6520 },
6521 "Ext.app.bind.Stub": {
6522 "idx": 200,
6523 "alias": [],
6524 "alternates": []
6525 },
6526 "Ext.app.bind.Template": {
6527 "idx": 205,
6528 "alias": [],
6529 "alternates": []
6530 },
6531 "Ext.app.bind.TemplateBinding": {
6532 "idx": 206,
6533 "alias": [],
6534 "alternates": []
6535 },
6536 "Ext.app.domain.Component": {
6537 "idx": 90,
6538 "alias": [],
6539 "alternates": []
6540 },
6541 "Ext.app.domain.Controller": {
6542 "idx": 209,
6543 "alias": [],
6544 "alternates": []
6545 },
6546 "Ext.app.domain.Direct": {
6547 "idx": 212,
6548 "alias": [],
6549 "alternates": []
6550 },
6551 "Ext.app.domain.Global": {
6552 "idx": 122,
6553 "alias": [],
6554 "alternates": []
6555 },
6556 "Ext.app.domain.Store": {
6557 "idx": 176,
6558 "alias": [],
6559 "alternates": []
6560 },
6561 "Ext.app.domain.View": {
6562 "idx": 184,
6563 "alias": [],
6564 "alternates": []
6565 },
6566 "Ext.app.route.Queue": {
6567 "idx": 177,
6568 "alias": [],
6569 "alternates": []
6570 },
6571 "Ext.app.route.Route": {
6572 "idx": 178,
6573 "alias": [],
6574 "alternates": []
6575 },
6576 "Ext.app.route.Router": {
6577 "idx": 180,
6578 "alias": [],
6579 "alternates": []
6580 },
6581 "Ext.button.Button": {
6582 "idx": 349,
6583 "alias": [
6584 "widget.button"
6585 ],
6586 "alternates": [
6587 "Ext.Button"
6588 ]
6589 },
6590 "Ext.button.Cycle": {
6591 "idx": 351,
6592 "alias": [
6593 "widget.cycle"
6594 ],
6595 "alternates": [
6596 "Ext.CycleButton"
6597 ]
6598 },
6599 "Ext.button.Manager": {
6600 "idx": 346,
6601 "alias": [],
6602 "alternates": [
6603 "Ext.ButtonToggleManager"
6604 ]
6605 },
6606 "Ext.button.Segmented": {
6607 "idx": 353,
6608 "alias": [
6609 "widget.segmentedbutton"
6610 ],
6611 "alternates": []
6612 },
6613 "Ext.button.Split": {
6614 "idx": 350,
6615 "alias": [
6616 "widget.splitbutton"
6617 ],
6618 "alternates": [
6619 "Ext.SplitButton"
6620 ]
6621 },
6622 "Ext.container.ButtonGroup": {
6623 "idx": 381,
6624 "alias": [
6625 "widget.buttongroup"
6626 ],
6627 "alternates": [
6628 "Ext.ButtonGroup"
6629 ]
6630 },
6631 "Ext.container.Container": {
6632 "idx": 334,
6633 "alias": [
6634 "widget.container"
6635 ],
6636 "alternates": [
6637 "Ext.Container",
6638 "Ext.AbstractContainer"
6639 ]
6640 },
6641 "Ext.container.DockingContainer": {
6642 "idx": 378,
6643 "alias": [],
6644 "alternates": []
6645 },
6646 "Ext.container.Monitor": {
6647 "idx": 382,
6648 "alias": [],
6649 "alternates": []
6650 },
6651 "Ext.container.Viewport": {
6652 "idx": 385,
6653 "alias": [
6654 "widget.viewport"
6655 ],
6656 "alternates": [
6657 "Ext.Viewport"
6658 ]
6659 },
6660 "Ext.dashboard.Column": {
6661 "idx": 388,
6662 "alias": [
6663 "widget.dashboard-column"
6664 ],
6665 "alternates": []
6666 },
6667 "Ext.dashboard.Dashboard": {
6668 "idx": 400,
6669 "alias": [
6670 "widget.dashboard"
6671 ],
6672 "alternates": []
6673 },
6674 "Ext.dashboard.DropZone": {
6675 "idx": 398,
6676 "alias": [],
6677 "alternates": []
6678 },
6679 "Ext.dashboard.Panel": {
6680 "idx": 387,
6681 "alias": [
6682 "widget.dashboard-panel"
6683 ],
6684 "alternates": []
6685 },
6686 "Ext.dashboard.Part": {
6687 "idx": 399,
6688 "alias": [
6689 "part.part"
6690 ],
6691 "alternates": []
6692 },
6693 "Ext.data.AbstractStore": {
6694 "idx": 137,
6695 "alias": [],
6696 "alternates": []
6697 },
6698 "Ext.data.ArrayStore": {
6699 "idx": 174,
6700 "alias": [
6701 "store.array"
6702 ],
6703 "alternates": [
6704 "Ext.data.SimpleStore"
6705 ]
6706 },
6707 "Ext.data.Batch": {
6708 "idx": 188,
6709 "alias": [],
6710 "alternates": []
6711 },
6712 "Ext.data.BufferedStore": {
6713 "idx": 214,
6714 "alias": [
6715 "store.buffered"
6716 ],
6717 "alternates": []
6718 },
6719 "Ext.data.ChainedStore": {
6720 "idx": 207,
6721 "alias": [
6722 "store.chained"
6723 ],
6724 "alternates": []
6725 },
6726 "Ext.data.Connection": {
6727 "idx": 17,
6728 "alias": [],
6729 "alternates": []
6730 },
6731 "Ext.data.DirectStore": {
6732 "idx": 216,
6733 "alias": [
6734 "store.direct"
6735 ],
6736 "alternates": []
6737 },
6738 "Ext.data.Error": {
6739 "idx": 138,
6740 "alias": [],
6741 "alternates": []
6742 },
6743 "Ext.data.ErrorCollection": {
6744 "idx": 139,
6745 "alias": [],
6746 "alternates": [
6747 "Ext.data.Errors"
6748 ]
6749 },
6750 "Ext.data.JsonP": {
6751 "idx": 217,
6752 "alias": [],
6753 "alternates": []
6754 },
6755 "Ext.data.JsonPStore": {
6756 "idx": 219,
6757 "alias": [
6758 "store.jsonp"
6759 ],
6760 "alternates": []
6761 },
6762 "Ext.data.JsonStore": {
6763 "idx": 220,
6764 "alias": [
6765 "store.json"
6766 ],
6767 "alternates": []
6768 },
6769 "Ext.data.LocalStore": {
6770 "idx": 163,
6771 "alias": [],
6772 "alternates": []
6773 },
6774 "Ext.data.Model": {
6775 "idx": 155,
6776 "alias": [],
6777 "alternates": [
6778 "Ext.data.Record"
6779 ]
6780 },
6781 "Ext.data.ModelManager": {
6782 "idx": 221,
6783 "alias": [],
6784 "alternates": [
6785 "Ext.ModelMgr"
6786 ]
6787 },
6788 "Ext.data.NodeInterface": {
6789 "idx": 222,
6790 "alias": [],
6791 "alternates": []
6792 },
6793 "Ext.data.NodeStore": {
6794 "idx": 225,
6795 "alias": [
6796 "store.node"
6797 ],
6798 "alternates": []
6799 },
6800 "Ext.data.PageMap": {
6801 "idx": 213,
6802 "alias": [],
6803 "alternates": []
6804 },
6805 "Ext.data.ProxyStore": {
6806 "idx": 162,
6807 "alias": [],
6808 "alternates": []
6809 },
6810 "Ext.data.Request": {
6811 "idx": 226,
6812 "alias": [],
6813 "alternates": []
6814 },
6815 "Ext.data.ResultSet": {
6816 "idx": 156,
6817 "alias": [],
6818 "alternates": []
6819 },
6820 "Ext.data.Session": {
6821 "idx": 195,
6822 "alias": [],
6823 "alternates": []
6824 },
6825 "Ext.data.SortTypes": {
6826 "idx": 145,
6827 "alias": [],
6828 "alternates": []
6829 },
6830 "Ext.data.Store": {
6831 "idx": 172,
6832 "alias": [
6833 "store.store"
6834 ],
6835 "alternates": []
6836 },
6837 "Ext.data.StoreManager": {
6838 "idx": 175,
6839 "alias": [],
6840 "alternates": [
6841 "Ext.StoreMgr",
6842 "Ext.data.StoreMgr",
6843 "Ext.StoreManager"
6844 ]
6845 },
6846 "Ext.data.TreeModel": {
6847 "idx": 224,
6848 "alias": [],
6849 "alternates": []
6850 },
6851 "Ext.data.TreeStore": {
6852 "idx": 227,
6853 "alias": [
6854 "store.tree"
6855 ],
6856 "alternates": []
6857 },
6858 "Ext.data.Types": {
6859 "idx": 228,
6860 "alias": [],
6861 "alternates": []
6862 },
6863 "Ext.data.Validation": {
6864 "idx": 229,
6865 "alias": [],
6866 "alternates": []
6867 },
6868 "Ext.data.XmlStore": {
6869 "idx": 234,
6870 "alias": [
6871 "store.xml"
6872 ],
6873 "alternates": []
6874 },
6875 "Ext.data.field.Boolean": {
6876 "idx": 148,
6877 "alias": [
6878 "data.field.bool",
6879 "data.field.boolean"
6880 ],
6881 "alternates": []
6882 },
6883 "Ext.data.field.Date": {
6884 "idx": 149,
6885 "alias": [
6886 "data.field.date"
6887 ],
6888 "alternates": []
6889 },
6890 "Ext.data.field.Field": {
6891 "idx": 147,
6892 "alias": [
6893 "data.field.auto"
6894 ],
6895 "alternates": [
6896 "Ext.data.Field"
6897 ]
6898 },
6899 "Ext.data.field.Integer": {
6900 "idx": 150,
6901 "alias": [
6902 "data.field.int",
6903 "data.field.integer"
6904 ],
6905 "alternates": []
6906 },
6907 "Ext.data.field.Number": {
6908 "idx": 151,
6909 "alias": [
6910 "data.field.float",
6911 "data.field.number"
6912 ],
6913 "alternates": []
6914 },
6915 "Ext.data.field.String": {
6916 "idx": 152,
6917 "alias": [
6918 "data.field.string"
6919 ],
6920 "alternates": []
6921 },
6922 "Ext.data.flash.BinaryXhr": {
6923 "idx": 14,
6924 "alias": [],
6925 "alternates": []
6926 },
6927 "Ext.data.identifier.Generator": {
6928 "idx": 153,
6929 "alias": [
6930 "data.identifier.default"
6931 ],
6932 "alternates": []
6933 },
6934 "Ext.data.identifier.Negative": {
6935 "idx": 235,
6936 "alias": [
6937 "data.identifier.negative"
6938 ],
6939 "alternates": []
6940 },
6941 "Ext.data.identifier.Sequential": {
6942 "idx": 154,
6943 "alias": [
6944 "data.identifier.sequential"
6945 ],
6946 "alternates": []
6947 },
6948 "Ext.data.identifier.Uuid": {
6949 "idx": 236,
6950 "alias": [
6951 "data.identifier.uuid"
6952 ],
6953 "alternates": []
6954 },
6955 "Ext.data.matrix.Matrix": {
6956 "idx": 191,
6957 "alias": [],
6958 "alternates": []
6959 },
6960 "Ext.data.matrix.Side": {
6961 "idx": 190,
6962 "alias": [],
6963 "alternates": []
6964 },
6965 "Ext.data.matrix.Slice": {
6966 "idx": 189,
6967 "alias": [],
6968 "alternates": []
6969 },
6970 "Ext.data.operation.Create": {
6971 "idx": 141,
6972 "alias": [
6973 "data.operation.create"
6974 ],
6975 "alternates": []
6976 },
6977 "Ext.data.operation.Destroy": {
6978 "idx": 142,
6979 "alias": [
6980 "data.operation.destroy"
6981 ],
6982 "alternates": []
6983 },
6984 "Ext.data.operation.Operation": {
6985 "idx": 140,
6986 "alias": [],
6987 "alternates": [
6988 "Ext.data.Operation"
6989 ]
6990 },
6991 "Ext.data.operation.Read": {
6992 "idx": 143,
6993 "alias": [
6994 "data.operation.read"
6995 ],
6996 "alternates": []
6997 },
6998 "Ext.data.operation.Update": {
6999 "idx": 144,
7000 "alias": [
7001 "data.operation.update"
7002 ],
7003 "alternates": []
7004 },
7005 "Ext.data.proxy.Ajax": {
7006 "idx": 165,
7007 "alias": [
7008 "proxy.ajax"
7009 ],
7010 "alternates": [
7011 "Ext.data.HttpProxy",
7012 "Ext.data.AjaxProxy"
7013 ]
7014 },
7015 "Ext.data.proxy.Client": {
7016 "idx": 160,
7017 "alias": [],
7018 "alternates": [
7019 "Ext.data.ClientProxy"
7020 ]
7021 },
7022 "Ext.data.proxy.Direct": {
7023 "idx": 215,
7024 "alias": [
7025 "proxy.direct"
7026 ],
7027 "alternates": [
7028 "Ext.data.DirectProxy"
7029 ]
7030 },
7031 "Ext.data.proxy.JsonP": {
7032 "idx": 218,
7033 "alias": [
7034 "proxy.jsonp",
7035 "proxy.scripttag"
7036 ],
7037 "alternates": [
7038 "Ext.data.ScriptTagProxy"
7039 ]
7040 },
7041 "Ext.data.proxy.LocalStorage": {
7042 "idx": 238,
7043 "alias": [
7044 "proxy.localstorage"
7045 ],
7046 "alternates": [
7047 "Ext.data.LocalStorageProxy"
7048 ]
7049 },
7050 "Ext.data.proxy.Memory": {
7051 "idx": 161,
7052 "alias": [
7053 "proxy.memory"
7054 ],
7055 "alternates": [
7056 "Ext.data.MemoryProxy"
7057 ]
7058 },
7059 "Ext.data.proxy.Proxy": {
7060 "idx": 159,
7061 "alias": [
7062 "proxy.proxy"
7063 ],
7064 "alternates": [
7065 "Ext.data.DataProxy",
7066 "Ext.data.Proxy"
7067 ]
7068 },
7069 "Ext.data.proxy.Rest": {
7070 "idx": 239,
7071 "alias": [
7072 "proxy.rest"
7073 ],
7074 "alternates": [
7075 "Ext.data.RestProxy"
7076 ]
7077 },
7078 "Ext.data.proxy.Server": {
7079 "idx": 164,
7080 "alias": [
7081 "proxy.server"
7082 ],
7083 "alternates": [
7084 "Ext.data.ServerProxy"
7085 ]
7086 },
7087 "Ext.data.proxy.SessionStorage": {
7088 "idx": 240,
7089 "alias": [
7090 "proxy.sessionstorage"
7091 ],
7092 "alternates": [
7093 "Ext.data.SessionStorageProxy"
7094 ]
7095 },
7096 "Ext.data.proxy.WebStorage": {
7097 "idx": 237,
7098 "alias": [],
7099 "alternates": [
7100 "Ext.data.WebStorageProxy"
7101 ]
7102 },
7103 "Ext.data.reader.Array": {
7104 "idx": 173,
7105 "alias": [
7106 "reader.array"
7107 ],
7108 "alternates": [
7109 "Ext.data.ArrayReader"
7110 ]
7111 },
7112 "Ext.data.reader.Json": {
7113 "idx": 166,
7114 "alias": [
7115 "reader.json"
7116 ],
7117 "alternates": [
7118 "Ext.data.JsonReader"
7119 ]
7120 },
7121 "Ext.data.reader.Reader": {
7122 "idx": 157,
7123 "alias": [
7124 "reader.base"
7125 ],
7126 "alternates": [
7127 "Ext.data.Reader",
7128 "Ext.data.DataReader"
7129 ]
7130 },
7131 "Ext.data.reader.Xml": {
7132 "idx": 232,
7133 "alias": [
7134 "reader.xml"
7135 ],
7136 "alternates": [
7137 "Ext.data.XmlReader"
7138 ]
7139 },
7140 "Ext.data.request.Ajax": {
7141 "idx": 15,
7142 "alias": [
7143 "request.ajax"
7144 ],
7145 "alternates": []
7146 },
7147 "Ext.data.request.Base": {
7148 "idx": 13,
7149 "alias": [],
7150 "alternates": []
7151 },
7152 "Ext.data.request.Form": {
7153 "idx": 16,
7154 "alias": [
7155 "request.form"
7156 ],
7157 "alternates": []
7158 },
7159 "Ext.data.schema.Association": {
7160 "idx": 130,
7161 "alias": [],
7162 "alternates": []
7163 },
7164 "Ext.data.schema.ManyToMany": {
7165 "idx": 133,
7166 "alias": [],
7167 "alternates": []
7168 },
7169 "Ext.data.schema.ManyToOne": {
7170 "idx": 132,
7171 "alias": [],
7172 "alternates": []
7173 },
7174 "Ext.data.schema.Namer": {
7175 "idx": 135,
7176 "alias": [
7177 "namer.default"
7178 ],
7179 "alternates": []
7180 },
7181 "Ext.data.schema.OneToOne": {
7182 "idx": 131,
7183 "alias": [],
7184 "alternates": []
7185 },
7186 "Ext.data.schema.Role": {
7187 "idx": 129,
7188 "alias": [],
7189 "alternates": []
7190 },
7191 "Ext.data.schema.Schema": {
7192 "idx": 136,
7193 "alias": [
7194 "schema.default"
7195 ],
7196 "alternates": []
7197 },
7198 "Ext.data.session.BatchVisitor": {
7199 "idx": 194,
7200 "alias": [],
7201 "alternates": []
7202 },
7203 "Ext.data.session.ChangesVisitor": {
7204 "idx": 192,
7205 "alias": [],
7206 "alternates": []
7207 },
7208 "Ext.data.session.ChildChangesVisitor": {
7209 "idx": 193,
7210 "alias": [],
7211 "alternates": []
7212 },
7213 "Ext.data.validator.Bound": {
7214 "idx": 241,
7215 "alias": [
7216 "data.validator.bound"
7217 ],
7218 "alternates": []
7219 },
7220 "Ext.data.validator.Email": {
7221 "idx": 243,
7222 "alias": [
7223 "data.validator.email"
7224 ],
7225 "alternates": []
7226 },
7227 "Ext.data.validator.Exclusion": {
7228 "idx": 245,
7229 "alias": [
7230 "data.validator.exclusion"
7231 ],
7232 "alternates": []
7233 },
7234 "Ext.data.validator.Format": {
7235 "idx": 242,
7236 "alias": [
7237 "data.validator.format"
7238 ],
7239 "alternates": []
7240 },
7241 "Ext.data.validator.Inclusion": {
7242 "idx": 246,
7243 "alias": [
7244 "data.validator.inclusion"
7245 ],
7246 "alternates": []
7247 },
7248 "Ext.data.validator.Length": {
7249 "idx": 247,
7250 "alias": [
7251 "data.validator.length"
7252 ],
7253 "alternates": []
7254 },
7255 "Ext.data.validator.List": {
7256 "idx": 244,
7257 "alias": [
7258 "data.validator.list"
7259 ],
7260 "alternates": []
7261 },
7262 "Ext.data.validator.Presence": {
7263 "idx": 248,
7264 "alias": [
7265 "data.validator.presence"
7266 ],
7267 "alternates": []
7268 },
7269 "Ext.data.validator.Range": {
7270 "idx": 249,
7271 "alias": [
7272 "data.validator.range"
7273 ],
7274 "alternates": []
7275 },
7276 "Ext.data.validator.Validator": {
7277 "idx": 146,
7278 "alias": [
7279 "data.validator.base"
7280 ],
7281 "alternates": []
7282 },
7283 "Ext.data.writer.Json": {
7284 "idx": 167,
7285 "alias": [
7286 "writer.json"
7287 ],
7288 "alternates": [
7289 "Ext.data.JsonWriter"
7290 ]
7291 },
7292 "Ext.data.writer.Writer": {
7293 "idx": 158,
7294 "alias": [
7295 "writer.base"
7296 ],
7297 "alternates": [
7298 "Ext.data.DataWriter",
7299 "Ext.data.Writer"
7300 ]
7301 },
7302 "Ext.data.writer.Xml": {
7303 "idx": 233,
7304 "alias": [
7305 "writer.xml"
7306 ],
7307 "alternates": [
7308 "Ext.data.XmlWriter"
7309 ]
7310 },
7311 "Ext.dd.DD": {
7312 "idx": 370,
7313 "alias": [],
7314 "alternates": []
7315 },
7316 "Ext.dd.DDProxy": {
7317 "idx": 371,
7318 "alias": [],
7319 "alternates": []
7320 },
7321 "Ext.dd.DDTarget": {
7322 "idx": 395,
7323 "alias": [],
7324 "alternates": []
7325 },
7326 "Ext.dd.DragDrop": {
7327 "idx": 369,
7328 "alias": [],
7329 "alternates": []
7330 },
7331 "Ext.dd.DragDropManager": {
7332 "idx": 363,
7333 "alias": [],
7334 "alternates": [
7335 "Ext.dd.DragDropMgr",
7336 "Ext.dd.DDM"
7337 ]
7338 },
7339 "Ext.dd.DragSource": {
7340 "idx": 373,
7341 "alias": [],
7342 "alternates": []
7343 },
7344 "Ext.dd.DragTracker": {
7345 "idx": 390,
7346 "alias": [],
7347 "alternates": []
7348 },
7349 "Ext.dd.DragZone": {
7350 "idx": 401,
7351 "alias": [],
7352 "alternates": []
7353 },
7354 "Ext.dd.DropTarget": {
7355 "idx": 397,
7356 "alias": [],
7357 "alternates": []
7358 },
7359 "Ext.dd.DropZone": {
7360 "idx": 403,
7361 "alias": [],
7362 "alternates": []
7363 },
7364 "Ext.dd.Registry": {
7365 "idx": 402,
7366 "alias": [],
7367 "alternates": []
7368 },
7369 "Ext.dd.ScrollManager": {
7370 "idx": 396,
7371 "alias": [],
7372 "alternates": []
7373 },
7374 "Ext.dd.StatusProxy": {
7375 "idx": 372,
7376 "alias": [],
7377 "alternates": []
7378 },
7379 "Ext.direct.Event": {
7380 "idx": 250,
7381 "alias": [
7382 "direct.event"
7383 ],
7384 "alternates": []
7385 },
7386 "Ext.direct.ExceptionEvent": {
7387 "idx": 252,
7388 "alias": [
7389 "direct.exception"
7390 ],
7391 "alternates": []
7392 },
7393 "Ext.direct.JsonProvider": {
7394 "idx": 253,
7395 "alias": [
7396 "direct.jsonprovider"
7397 ],
7398 "alternates": []
7399 },
7400 "Ext.direct.Manager": {
7401 "idx": 210,
7402 "alias": [],
7403 "alternates": []
7404 },
7405 "Ext.direct.PollingProvider": {
7406 "idx": 254,
7407 "alias": [
7408 "direct.pollingprovider"
7409 ],
7410 "alternates": []
7411 },
7412 "Ext.direct.Provider": {
7413 "idx": 211,
7414 "alias": [
7415 "direct.provider"
7416 ],
7417 "alternates": []
7418 },
7419 "Ext.direct.RemotingEvent": {
7420 "idx": 251,
7421 "alias": [
7422 "direct.rpc"
7423 ],
7424 "alternates": []
7425 },
7426 "Ext.direct.RemotingMethod": {
7427 "idx": 255,
7428 "alias": [],
7429 "alternates": []
7430 },
7431 "Ext.direct.RemotingProvider": {
7432 "idx": 257,
7433 "alias": [
7434 "direct.remotingprovider"
7435 ],
7436 "alternates": []
7437 },
7438 "Ext.direct.Transaction": {
7439 "idx": 256,
7440 "alias": [
7441 "direct.transaction"
7442 ],
7443 "alternates": []
7444 },
7445 "Ext.dom.ButtonElement": {
7446 "idx": 345,
7447 "alias": [],
7448 "alternates": []
7449 },
7450 "Ext.dom.CompositeElement": {
7451 "idx": 92,
7452 "alias": [],
7453 "alternates": [
7454 "Ext.CompositeElement"
7455 ]
7456 },
7457 "Ext.dom.CompositeElementLite": {
7458 "idx": 75,
7459 "alias": [],
7460 "alternates": [
7461 "Ext.CompositeElementLite"
7462 ]
7463 },
7464 "Ext.dom.Element": {
7465 "idx": 49,
7466 "alias": [],
7467 "alternates": [
7468 "Ext.Element"
7469 ]
7470 },
7471 "Ext.dom.ElementEvent": {
7472 "idx": 30,
7473 "alias": [],
7474 "alternates": []
7475 },
7476 "Ext.dom.Fly": {
7477 "idx": 74,
7478 "alias": [],
7479 "alternates": [
7480 "Ext.dom.Element.Fly"
7481 ]
7482 },
7483 "Ext.dom.GarbageCollector": {
7484 "idx": 258,
7485 "alias": [],
7486 "alternates": []
7487 },
7488 "Ext.dom.Helper": {
7489 "idx": 230,
7490 "alias": [],
7491 "alternates": [
7492 "Ext.DomHelper",
7493 "Ext.core.DomHelper"
7494 ]
7495 },
7496 "Ext.dom.Layer": {
7497 "idx": 404,
7498 "alias": [],
7499 "alternates": [
7500 "Ext.Layer"
7501 ]
7502 },
7503 "Ext.dom.Query": {
7504 "idx": 231,
7505 "alias": [],
7506 "alternates": [
7507 "Ext.core.DomQuery",
7508 "Ext.DomQuery"
7509 ]
7510 },
7511 "Ext.dom.Shadow": {
7512 "idx": 28,
7513 "alias": [],
7514 "alternates": [
7515 "Ext.Shadow"
7516 ]
7517 },
7518 "Ext.dom.Shim": {
7519 "idx": 29,
7520 "alias": [],
7521 "alternates": []
7522 },
7523 "Ext.dom.Underlay": {
7524 "idx": 27,
7525 "alias": [],
7526 "alternates": []
7527 },
7528 "Ext.dom.UnderlayPool": {
7529 "idx": 26,
7530 "alias": [],
7531 "alternates": []
7532 },
7533 "Ext.event.Event": {
7534 "idx": 35,
7535 "alias": [],
7536 "alternates": [
7537 "Ext.EventObjectImpl"
7538 ]
7539 },
7540 "Ext.event.gesture.DoubleTap": {
7541 "idx": 261,
7542 "alias": [],
7543 "alternates": []
7544 },
7545 "Ext.event.gesture.Drag": {
7546 "idx": 262,
7547 "alias": [],
7548 "alternates": []
7549 },
7550 "Ext.event.gesture.EdgeSwipe": {
7551 "idx": 264,
7552 "alias": [],
7553 "alternates": []
7554 },
7555 "Ext.event.gesture.LongPress": {
7556 "idx": 265,
7557 "alias": [],
7558 "alternates": []
7559 },
7560 "Ext.event.gesture.MultiTouch": {
7561 "idx": 266,
7562 "alias": [],
7563 "alternates": []
7564 },
7565 "Ext.event.gesture.Pinch": {
7566 "idx": 267,
7567 "alias": [],
7568 "alternates": []
7569 },
7570 "Ext.event.gesture.Recognizer": {
7571 "idx": 259,
7572 "alias": [],
7573 "alternates": []
7574 },
7575 "Ext.event.gesture.Rotate": {
7576 "idx": 268,
7577 "alias": [],
7578 "alternates": []
7579 },
7580 "Ext.event.gesture.SingleTouch": {
7581 "idx": 260,
7582 "alias": [],
7583 "alternates": []
7584 },
7585 "Ext.event.gesture.Swipe": {
7586 "idx": 263,
7587 "alias": [],
7588 "alternates": []
7589 },
7590 "Ext.event.gesture.Tap": {
7591 "idx": 269,
7592 "alias": [],
7593 "alternates": []
7594 },
7595 "Ext.event.publisher.Dom": {
7596 "idx": 36,
7597 "alias": [],
7598 "alternates": []
7599 },
7600 "Ext.event.publisher.ElementPaint": {
7601 "idx": 48,
7602 "alias": [],
7603 "alternates": []
7604 },
7605 "Ext.event.publisher.ElementSize": {
7606 "idx": 44,
7607 "alias": [],
7608 "alternates": []
7609 },
7610 "Ext.event.publisher.Focus": {
7611 "idx": 270,
7612 "alias": [],
7613 "alternates": []
7614 },
7615 "Ext.event.publisher.Gesture": {
7616 "idx": 37,
7617 "alias": [],
7618 "alternates": []
7619 },
7620 "Ext.event.publisher.MouseEnterLeave": {
7621 "idx": 406,
7622 "alias": [],
7623 "alternates": []
7624 },
7625 "Ext.event.publisher.Publisher": {
7626 "idx": 31,
7627 "alias": [],
7628 "alternates": []
7629 },
7630 "Ext.flash.Component": {
7631 "idx": 407,
7632 "alias": [
7633 "widget.flash"
7634 ],
7635 "alternates": [
7636 "Ext.FlashComponent"
7637 ]
7638 },
7639 "Ext.form.Basic": {
7640 "idx": 422,
7641 "alias": [],
7642 "alternates": [
7643 "Ext.form.BasicForm"
7644 ]
7645 },
7646 "Ext.form.CheckboxGroup": {
7647 "idx": 429,
7648 "alias": [
7649 "widget.checkboxgroup"
7650 ],
7651 "alternates": []
7652 },
7653 "Ext.form.CheckboxManager": {
7654 "idx": 427,
7655 "alias": [],
7656 "alternates": []
7657 },
7658 "Ext.form.FieldAncestor": {
7659 "idx": 423,
7660 "alias": [],
7661 "alternates": []
7662 },
7663 "Ext.form.FieldContainer": {
7664 "idx": 425,
7665 "alias": [
7666 "widget.fieldcontainer"
7667 ],
7668 "alternates": []
7669 },
7670 "Ext.form.FieldSet": {
7671 "idx": 430,
7672 "alias": [
7673 "widget.fieldset"
7674 ],
7675 "alternates": []
7676 },
7677 "Ext.form.Label": {
7678 "idx": 431,
7679 "alias": [
7680 "widget.label"
7681 ],
7682 "alternates": []
7683 },
7684 "Ext.form.Labelable": {
7685 "idx": 414,
7686 "alias": [],
7687 "alternates": []
7688 },
7689 "Ext.form.Panel": {
7690 "idx": 432,
7691 "alias": [
7692 "widget.form"
7693 ],
7694 "alternates": [
7695 "Ext.FormPanel",
7696 "Ext.form.FormPanel"
7697 ]
7698 },
7699 "Ext.form.RadioGroup": {
7700 "idx": 435,
7701 "alias": [
7702 "widget.radiogroup"
7703 ],
7704 "alternates": []
7705 },
7706 "Ext.form.RadioManager": {
7707 "idx": 433,
7708 "alias": [],
7709 "alternates": []
7710 },
7711 "Ext.form.action.Action": {
7712 "idx": 408,
7713 "alias": [],
7714 "alternates": [
7715 "Ext.form.Action"
7716 ]
7717 },
7718 "Ext.form.action.DirectAction": {
7719 "idx": 436,
7720 "alias": [],
7721 "alternates": []
7722 },
7723 "Ext.form.action.DirectLoad": {
7724 "idx": 437,
7725 "alias": [
7726 "formaction.directload"
7727 ],
7728 "alternates": [
7729 "Ext.form.Action.DirectLoad"
7730 ]
7731 },
7732 "Ext.form.action.DirectSubmit": {
7733 "idx": 438,
7734 "alias": [
7735 "formaction.directsubmit"
7736 ],
7737 "alternates": [
7738 "Ext.form.Action.DirectSubmit"
7739 ]
7740 },
7741 "Ext.form.action.Load": {
7742 "idx": 409,
7743 "alias": [
7744 "formaction.load"
7745 ],
7746 "alternates": [
7747 "Ext.form.Action.Load"
7748 ]
7749 },
7750 "Ext.form.action.StandardSubmit": {
7751 "idx": 439,
7752 "alias": [
7753 "formaction.standardsubmit"
7754 ],
7755 "alternates": []
7756 },
7757 "Ext.form.action.Submit": {
7758 "idx": 410,
7759 "alias": [
7760 "formaction.submit"
7761 ],
7762 "alternates": [
7763 "Ext.form.Action.Submit"
7764 ]
7765 },
7766 "Ext.form.field.Base": {
7767 "idx": 416,
7768 "alias": [
7769 "widget.field"
7770 ],
7771 "alternates": [
7772 "Ext.form.Field",
7773 "Ext.form.BaseField"
7774 ]
7775 },
7776 "Ext.form.field.Checkbox": {
7777 "idx": 428,
7778 "alias": [
7779 "widget.checkbox",
7780 "widget.checkboxfield"
7781 ],
7782 "alternates": [
7783 "Ext.form.Checkbox"
7784 ]
7785 },
7786 "Ext.form.field.ComboBox": {
7787 "idx": 455,
7788 "alias": [
7789 "widget.combo",
7790 "widget.combobox"
7791 ],
7792 "alternates": [
7793 "Ext.form.ComboBox"
7794 ]
7795 },
7796 "Ext.form.field.Date": {
7797 "idx": 458,
7798 "alias": [
7799 "widget.datefield"
7800 ],
7801 "alternates": [
7802 "Ext.form.DateField",
7803 "Ext.form.Date"
7804 ]
7805 },
7806 "Ext.form.field.Display": {
7807 "idx": 459,
7808 "alias": [
7809 "widget.displayfield"
7810 ],
7811 "alternates": [
7812 "Ext.form.DisplayField",
7813 "Ext.form.Display"
7814 ]
7815 },
7816 "Ext.form.field.Field": {
7817 "idx": 415,
7818 "alias": [],
7819 "alternates": []
7820 },
7821 "Ext.form.field.File": {
7822 "idx": 462,
7823 "alias": [
7824 "widget.filefield",
7825 "widget.fileuploadfield"
7826 ],
7827 "alternates": [
7828 "Ext.form.FileUploadField",
7829 "Ext.ux.form.FileUploadField",
7830 "Ext.form.File"
7831 ]
7832 },
7833 "Ext.form.field.FileButton": {
7834 "idx": 460,
7835 "alias": [
7836 "widget.filebutton"
7837 ],
7838 "alternates": []
7839 },
7840 "Ext.form.field.Hidden": {
7841 "idx": 463,
7842 "alias": [
7843 "widget.hidden",
7844 "widget.hiddenfield"
7845 ],
7846 "alternates": [
7847 "Ext.form.Hidden"
7848 ]
7849 },
7850 "Ext.form.field.HtmlEditor": {
7851 "idx": 472,
7852 "alias": [
7853 "widget.htmleditor"
7854 ],
7855 "alternates": [
7856 "Ext.form.HtmlEditor"
7857 ]
7858 },
7859 "Ext.form.field.Number": {
7860 "idx": 452,
7861 "alias": [
7862 "widget.numberfield"
7863 ],
7864 "alternates": [
7865 "Ext.form.NumberField",
7866 "Ext.form.Number"
7867 ]
7868 },
7869 "Ext.form.field.Picker": {
7870 "idx": 440,
7871 "alias": [
7872 "widget.pickerfield"
7873 ],
7874 "alternates": [
7875 "Ext.form.Picker"
7876 ]
7877 },
7878 "Ext.form.field.Radio": {
7879 "idx": 434,
7880 "alias": [
7881 "widget.radio",
7882 "widget.radiofield"
7883 ],
7884 "alternates": [
7885 "Ext.form.Radio"
7886 ]
7887 },
7888 "Ext.form.field.Spinner": {
7889 "idx": 451,
7890 "alias": [
7891 "widget.spinnerfield"
7892 ],
7893 "alternates": [
7894 "Ext.form.Spinner"
7895 ]
7896 },
7897 "Ext.form.field.Tag": {
7898 "idx": 473,
7899 "alias": [
7900 "widget.tagfield"
7901 ],
7902 "alternates": []
7903 },
7904 "Ext.form.field.Text": {
7905 "idx": 419,
7906 "alias": [
7907 "widget.textfield"
7908 ],
7909 "alternates": [
7910 "Ext.form.TextField",
7911 "Ext.form.Text"
7912 ]
7913 },
7914 "Ext.form.field.TextArea": {
7915 "idx": 420,
7916 "alias": [
7917 "widget.textarea",
7918 "widget.textareafield"
7919 ],
7920 "alternates": [
7921 "Ext.form.TextArea"
7922 ]
7923 },
7924 "Ext.form.field.Time": {
7925 "idx": 475,
7926 "alias": [
7927 "widget.timefield"
7928 ],
7929 "alternates": [
7930 "Ext.form.TimeField",
7931 "Ext.form.Time"
7932 ]
7933 },
7934 "Ext.form.field.Trigger": {
7935 "idx": 476,
7936 "alias": [
7937 "widget.trigger",
7938 "widget.triggerfield"
7939 ],
7940 "alternates": [
7941 "Ext.form.TriggerField",
7942 "Ext.form.TwinTriggerField",
7943 "Ext.form.Trigger"
7944 ]
7945 },
7946 "Ext.form.field.VTypes": {
7947 "idx": 417,
7948 "alias": [],
7949 "alternates": [
7950 "Ext.form.VTypes"
7951 ]
7952 },
7953 "Ext.form.trigger.Component": {
7954 "idx": 461,
7955 "alias": [
7956 "trigger.component"
7957 ],
7958 "alternates": []
7959 },
7960 "Ext.form.trigger.Spinner": {
7961 "idx": 450,
7962 "alias": [
7963 "trigger.spinner"
7964 ],
7965 "alternates": []
7966 },
7967 "Ext.form.trigger.Trigger": {
7968 "idx": 418,
7969 "alias": [
7970 "trigger.trigger"
7971 ],
7972 "alternates": []
7973 },
7974 "Ext.fx.Anim": {
7975 "idx": 72,
7976 "alias": [],
7977 "alternates": []
7978 },
7979 "Ext.fx.Animation": {
7980 "idx": 280,
7981 "alias": [],
7982 "alternates": []
7983 },
7984 "Ext.fx.Animator": {
7985 "idx": 67,
7986 "alias": [],
7987 "alternates": []
7988 },
7989 "Ext.fx.CubicBezier": {
7990 "idx": 68,
7991 "alias": [],
7992 "alternates": []
7993 },
7994 "Ext.fx.DrawPath": {
7995 "idx": 70,
7996 "alias": [],
7997 "alternates": []
7998 },
7999 "Ext.fx.Easing": {
8000 "idx": 69,
8001 "alias": [],
8002 "alternates": []
8003 },
8004 "Ext.fx.Manager": {
8005 "idx": 66,
8006 "alias": [],
8007 "alternates": []
8008 },
8009 "Ext.fx.PropertyHandler": {
8010 "idx": 71,
8011 "alias": [],
8012 "alternates": []
8013 },
8014 "Ext.fx.Queue": {
8015 "idx": 65,
8016 "alias": [],
8017 "alternates": []
8018 },
8019 "Ext.fx.Runner": {
8020 "idx": 283,
8021 "alias": [],
8022 "alternates": []
8023 },
8024 "Ext.fx.State": {
8025 "idx": 271,
8026 "alias": [],
8027 "alternates": []
8028 },
8029 "Ext.fx.animation.Abstract": {
8030 "idx": 272,
8031 "alias": [],
8032 "alternates": []
8033 },
8034 "Ext.fx.animation.Cube": {
8035 "idx": 284,
8036 "alias": [
8037 "animation.cube"
8038 ],
8039 "alternates": []
8040 },
8041 "Ext.fx.animation.Fade": {
8042 "idx": 275,
8043 "alias": [
8044 "animation.fade",
8045 "animation.fadeIn"
8046 ],
8047 "alternates": [
8048 "Ext.fx.animation.FadeIn"
8049 ]
8050 },
8051 "Ext.fx.animation.FadeOut": {
8052 "idx": 276,
8053 "alias": [
8054 "animation.fadeOut"
8055 ],
8056 "alternates": []
8057 },
8058 "Ext.fx.animation.Flip": {
8059 "idx": 277,
8060 "alias": [
8061 "animation.flip"
8062 ],
8063 "alternates": []
8064 },
8065 "Ext.fx.animation.Pop": {
8066 "idx": 278,
8067 "alias": [
8068 "animation.pop",
8069 "animation.popIn"
8070 ],
8071 "alternates": [
8072 "Ext.fx.animation.PopIn"
8073 ]
8074 },
8075 "Ext.fx.animation.PopOut": {
8076 "idx": 279,
8077 "alias": [
8078 "animation.popOut"
8079 ],
8080 "alternates": []
8081 },
8082 "Ext.fx.animation.Slide": {
8083 "idx": 273,
8084 "alias": [
8085 "animation.slide",
8086 "animation.slideIn"
8087 ],
8088 "alternates": [
8089 "Ext.fx.animation.SlideIn"
8090 ]
8091 },
8092 "Ext.fx.animation.SlideOut": {
8093 "idx": 274,
8094 "alias": [
8095 "animation.slideOut"
8096 ],
8097 "alternates": []
8098 },
8099 "Ext.fx.animation.Wipe": {
8100 "idx": 285,
8101 "alias": [],
8102 "alternates": [
8103 "Ext.fx.animation.WipeIn"
8104 ]
8105 },
8106 "Ext.fx.animation.WipeOut": {
8107 "idx": 286,
8108 "alias": [],
8109 "alternates": []
8110 },
8111 "Ext.fx.easing.Abstract": {
8112 "idx": 94,
8113 "alias": [],
8114 "alternates": []
8115 },
8116 "Ext.fx.easing.Bounce": {
8117 "idx": 96,
8118 "alias": [],
8119 "alternates": []
8120 },
8121 "Ext.fx.easing.BoundMomentum": {
8122 "idx": 97,
8123 "alias": [],
8124 "alternates": []
8125 },
8126 "Ext.fx.easing.EaseIn": {
8127 "idx": 287,
8128 "alias": [
8129 "easing.ease-in"
8130 ],
8131 "alternates": []
8132 },
8133 "Ext.fx.easing.EaseOut": {
8134 "idx": 99,
8135 "alias": [
8136 "easing.ease-out"
8137 ],
8138 "alternates": []
8139 },
8140 "Ext.fx.easing.Easing": {
8141 "idx": 288,
8142 "alias": [],
8143 "alternates": []
8144 },
8145 "Ext.fx.easing.Linear": {
8146 "idx": 98,
8147 "alias": [
8148 "easing.linear"
8149 ],
8150 "alternates": []
8151 },
8152 "Ext.fx.easing.Momentum": {
8153 "idx": 95,
8154 "alias": [],
8155 "alternates": []
8156 },
8157 "Ext.fx.layout.Card": {
8158 "idx": 298,
8159 "alias": [],
8160 "alternates": []
8161 },
8162 "Ext.fx.layout.card.Abstract": {
8163 "idx": 289,
8164 "alias": [],
8165 "alternates": []
8166 },
8167 "Ext.fx.layout.card.Cover": {
8168 "idx": 292,
8169 "alias": [
8170 "fx.layout.card.cover"
8171 ],
8172 "alternates": []
8173 },
8174 "Ext.fx.layout.card.Cube": {
8175 "idx": 299,
8176 "alias": [
8177 "fx.layout.card.cube"
8178 ],
8179 "alternates": []
8180 },
8181 "Ext.fx.layout.card.Fade": {
8182 "idx": 294,
8183 "alias": [
8184 "fx.layout.card.fade"
8185 ],
8186 "alternates": []
8187 },
8188 "Ext.fx.layout.card.Flip": {
8189 "idx": 295,
8190 "alias": [
8191 "fx.layout.card.flip"
8192 ],
8193 "alternates": []
8194 },
8195 "Ext.fx.layout.card.Pop": {
8196 "idx": 296,
8197 "alias": [
8198 "fx.layout.card.pop"
8199 ],
8200 "alternates": []
8201 },
8202 "Ext.fx.layout.card.Reveal": {
8203 "idx": 293,
8204 "alias": [
8205 "fx.layout.card.reveal"
8206 ],
8207 "alternates": []
8208 },
8209 "Ext.fx.layout.card.Scroll": {
8210 "idx": 297,
8211 "alias": [
8212 "fx.layout.card.scroll"
8213 ],
8214 "alternates": []
8215 },
8216 "Ext.fx.layout.card.ScrollCover": {
8217 "idx": 300,
8218 "alias": [
8219 "fx.layout.card.scrollcover"
8220 ],
8221 "alternates": []
8222 },
8223 "Ext.fx.layout.card.ScrollReveal": {
8224 "idx": 301,
8225 "alias": [
8226 "fx.layout.card.scrollreveal"
8227 ],
8228 "alternates": []
8229 },
8230 "Ext.fx.layout.card.Slide": {
8231 "idx": 291,
8232 "alias": [
8233 "fx.layout.card.slide"
8234 ],
8235 "alternates": []
8236 },
8237 "Ext.fx.layout.card.Style": {
8238 "idx": 290,
8239 "alias": [],
8240 "alternates": []
8241 },
8242 "Ext.fx.runner.Css": {
8243 "idx": 281,
8244 "alias": [],
8245 "alternates": []
8246 },
8247 "Ext.fx.runner.CssAnimation": {
8248 "idx": 302,
8249 "alias": [],
8250 "alternates": []
8251 },
8252 "Ext.fx.runner.CssTransition": {
8253 "idx": 282,
8254 "alias": [],
8255 "alternates": [
8256 "Ext.Animator"
8257 ]
8258 },
8259 "Ext.fx.target.Component": {
8260 "idx": 64,
8261 "alias": [],
8262 "alternates": []
8263 },
8264 "Ext.fx.target.CompositeElement": {
8265 "idx": 60,
8266 "alias": [],
8267 "alternates": []
8268 },
8269 "Ext.fx.target.CompositeElementCSS": {
8270 "idx": 61,
8271 "alias": [],
8272 "alternates": []
8273 },
8274 "Ext.fx.target.CompositeSprite": {
8275 "idx": 63,
8276 "alias": [],
8277 "alternates": []
8278 },
8279 "Ext.fx.target.Element": {
8280 "idx": 58,
8281 "alias": [],
8282 "alternates": []
8283 },
8284 "Ext.fx.target.ElementCSS": {
8285 "idx": 59,
8286 "alias": [],
8287 "alternates": []
8288 },
8289 "Ext.fx.target.Sprite": {
8290 "idx": 62,
8291 "alias": [],
8292 "alternates": []
8293 },
8294 "Ext.fx.target.Target": {
8295 "idx": 57,
8296 "alias": [],
8297 "alternates": []
8298 },
8299 "Ext.grid.CellContext": {
8300 "idx": 477,
8301 "alias": [],
8302 "alternates": []
8303 },
8304 "Ext.grid.CellEditor": {
8305 "idx": 478,
8306 "alias": [],
8307 "alternates": []
8308 },
8309 "Ext.grid.ColumnComponentLayout": {
8310 "idx": 479,
8311 "alias": [
8312 "layout.columncomponent"
8313 ],
8314 "alternates": []
8315 },
8316 "Ext.grid.ColumnLayout": {
8317 "idx": 482,
8318 "alias": [
8319 "layout.gridcolumn"
8320 ],
8321 "alternates": []
8322 },
8323 "Ext.grid.ColumnManager": {
8324 "idx": 483,
8325 "alias": [],
8326 "alternates": [
8327 "Ext.grid.ColumnModel"
8328 ]
8329 },
8330 "Ext.grid.NavigationModel": {
8331 "idx": 484,
8332 "alias": [
8333 "view.navigation.grid"
8334 ],
8335 "alternates": []
8336 },
8337 "Ext.grid.Panel": {
8338 "idx": 489,
8339 "alias": [
8340 "widget.grid",
8341 "widget.gridpanel"
8342 ],
8343 "alternates": [
8344 "Ext.list.ListView",
8345 "Ext.ListView",
8346 "Ext.grid.GridPanel"
8347 ]
8348 },
8349 "Ext.grid.RowEditor": {
8350 "idx": 491,
8351 "alias": [
8352 "widget.roweditor"
8353 ],
8354 "alternates": []
8355 },
8356 "Ext.grid.RowEditorButtons": {
8357 "idx": 490,
8358 "alias": [
8359 "widget.roweditorbuttons"
8360 ],
8361 "alternates": []
8362 },
8363 "Ext.grid.Scroller": {
8364 "idx": 492,
8365 "alias": [],
8366 "alternates": []
8367 },
8368 "Ext.grid.ViewDropZone": {
8369 "idx": 494,
8370 "alias": [],
8371 "alternates": []
8372 },
8373 "Ext.grid.column.Action": {
8374 "idx": 501,
8375 "alias": [
8376 "widget.actioncolumn"
8377 ],
8378 "alternates": [
8379 "Ext.grid.ActionColumn"
8380 ]
8381 },
8382 "Ext.grid.column.Boolean": {
8383 "idx": 502,
8384 "alias": [
8385 "widget.booleancolumn"
8386 ],
8387 "alternates": [
8388 "Ext.grid.BooleanColumn"
8389 ]
8390 },
8391 "Ext.grid.column.Check": {
8392 "idx": 503,
8393 "alias": [
8394 "widget.checkcolumn"
8395 ],
8396 "alternates": [
8397 "Ext.ux.CheckColumn",
8398 "Ext.grid.column.CheckColumn"
8399 ]
8400 },
8401 "Ext.grid.column.Column": {
8402 "idx": 500,
8403 "alias": [
8404 "widget.gridcolumn"
8405 ],
8406 "alternates": [
8407 "Ext.grid.Column"
8408 ]
8409 },
8410 "Ext.grid.column.Date": {
8411 "idx": 504,
8412 "alias": [
8413 "widget.datecolumn"
8414 ],
8415 "alternates": [
8416 "Ext.grid.DateColumn"
8417 ]
8418 },
8419 "Ext.grid.column.Number": {
8420 "idx": 505,
8421 "alias": [
8422 "widget.numbercolumn"
8423 ],
8424 "alternates": [
8425 "Ext.grid.NumberColumn"
8426 ]
8427 },
8428 "Ext.grid.column.RowNumberer": {
8429 "idx": 506,
8430 "alias": [
8431 "widget.rownumberer"
8432 ],
8433 "alternates": [
8434 "Ext.grid.RowNumberer"
8435 ]
8436 },
8437 "Ext.grid.column.Template": {
8438 "idx": 507,
8439 "alias": [
8440 "widget.templatecolumn"
8441 ],
8442 "alternates": [
8443 "Ext.grid.TemplateColumn"
8444 ]
8445 },
8446 "Ext.grid.column.Widget": {
8447 "idx": 508,
8448 "alias": [
8449 "widget.widgetcolumn"
8450 ],
8451 "alternates": []
8452 },
8453 "Ext.grid.feature.AbstractSummary": {
8454 "idx": 510,
8455 "alias": [
8456 "feature.abstractsummary"
8457 ],
8458 "alternates": []
8459 },
8460 "Ext.grid.feature.Feature": {
8461 "idx": 509,
8462 "alias": [
8463 "feature.feature"
8464 ],
8465 "alternates": []
8466 },
8467 "Ext.grid.feature.GroupStore": {
8468 "idx": 511,
8469 "alias": [],
8470 "alternates": []
8471 },
8472 "Ext.grid.feature.Grouping": {
8473 "idx": 512,
8474 "alias": [
8475 "feature.grouping"
8476 ],
8477 "alternates": []
8478 },
8479 "Ext.grid.feature.GroupingSummary": {
8480 "idx": 513,
8481 "alias": [
8482 "feature.groupingsummary"
8483 ],
8484 "alternates": []
8485 },
8486 "Ext.grid.feature.RowBody": {
8487 "idx": 514,
8488 "alias": [
8489 "feature.rowbody"
8490 ],
8491 "alternates": []
8492 },
8493 "Ext.grid.feature.Summary": {
8494 "idx": 515,
8495 "alias": [
8496 "feature.summary"
8497 ],
8498 "alternates": []
8499 },
8500 "Ext.grid.filters.Filters": {
8501 "idx": 528,
8502 "alias": [
8503 "plugin.gridfilters"
8504 ],
8505 "alternates": []
8506 },
8507 "Ext.grid.filters.filter.Base": {
8508 "idx": 520,
8509 "alias": [],
8510 "alternates": []
8511 },
8512 "Ext.grid.filters.filter.Boolean": {
8513 "idx": 522,
8514 "alias": [
8515 "grid.filter.boolean"
8516 ],
8517 "alternates": []
8518 },
8519 "Ext.grid.filters.filter.Date": {
8520 "idx": 524,
8521 "alias": [
8522 "grid.filter.date"
8523 ],
8524 "alternates": []
8525 },
8526 "Ext.grid.filters.filter.List": {
8527 "idx": 525,
8528 "alias": [
8529 "grid.filter.list"
8530 ],
8531 "alternates": []
8532 },
8533 "Ext.grid.filters.filter.Number": {
8534 "idx": 526,
8535 "alias": [
8536 "grid.filter.number",
8537 "grid.filter.numeric"
8538 ],
8539 "alternates": []
8540 },
8541 "Ext.grid.filters.filter.SingleFilter": {
8542 "idx": 521,
8543 "alias": [],
8544 "alternates": []
8545 },
8546 "Ext.grid.filters.filter.String": {
8547 "idx": 527,
8548 "alias": [
8549 "grid.filter.string"
8550 ],
8551 "alternates": []
8552 },
8553 "Ext.grid.filters.filter.TriFilter": {
8554 "idx": 523,
8555 "alias": [],
8556 "alternates": []
8557 },
8558 "Ext.grid.header.Container": {
8559 "idx": 499,
8560 "alias": [
8561 "widget.headercontainer"
8562 ],
8563 "alternates": []
8564 },
8565 "Ext.grid.header.DragZone": {
8566 "idx": 496,
8567 "alias": [],
8568 "alternates": []
8569 },
8570 "Ext.grid.header.DropZone": {
8571 "idx": 497,
8572 "alias": [],
8573 "alternates": []
8574 },
8575 "Ext.grid.locking.HeaderContainer": {
8576 "idx": 529,
8577 "alias": [],
8578 "alternates": []
8579 },
8580 "Ext.grid.locking.Lockable": {
8581 "idx": 531,
8582 "alias": [],
8583 "alternates": [
8584 "Ext.grid.Lockable"
8585 ]
8586 },
8587 "Ext.grid.locking.RowSynchronizer": {
8588 "idx": 486,
8589 "alias": [],
8590 "alternates": []
8591 },
8592 "Ext.grid.locking.View": {
8593 "idx": 530,
8594 "alias": [],
8595 "alternates": [
8596 "Ext.grid.LockingView"
8597 ]
8598 },
8599 "Ext.grid.plugin.BufferedRenderer": {
8600 "idx": 532,
8601 "alias": [
8602 "plugin.bufferedrenderer"
8603 ],
8604 "alternates": []
8605 },
8606 "Ext.grid.plugin.CellEditing": {
8607 "idx": 534,
8608 "alias": [
8609 "plugin.cellediting"
8610 ],
8611 "alternates": []
8612 },
8613 "Ext.grid.plugin.Clipboard": {
8614 "idx": 536,
8615 "alias": [
8616 "plugin.clipboard"
8617 ],
8618 "alternates": []
8619 },
8620 "Ext.grid.plugin.DragDrop": {
8621 "idx": 537,
8622 "alias": [
8623 "plugin.gridviewdragdrop"
8624 ],
8625 "alternates": []
8626 },
8627 "Ext.grid.plugin.Editing": {
8628 "idx": 533,
8629 "alias": [
8630 "editing.editing"
8631 ],
8632 "alternates": []
8633 },
8634 "Ext.grid.plugin.HeaderReorderer": {
8635 "idx": 498,
8636 "alias": [
8637 "plugin.gridheaderreorderer"
8638 ],
8639 "alternates": []
8640 },
8641 "Ext.grid.plugin.HeaderResizer": {
8642 "idx": 495,
8643 "alias": [
8644 "plugin.gridheaderresizer"
8645 ],
8646 "alternates": []
8647 },
8648 "Ext.grid.plugin.RowEditing": {
8649 "idx": 538,
8650 "alias": [
8651 "plugin.rowediting"
8652 ],
8653 "alternates": []
8654 },
8655 "Ext.grid.plugin.RowExpander": {
8656 "idx": 539,
8657 "alias": [
8658 "plugin.rowexpander"
8659 ],
8660 "alternates": []
8661 },
8662 "Ext.grid.property.Grid": {
8663 "idx": 540,
8664 "alias": [
8665 "widget.propertygrid"
8666 ],
8667 "alternates": [
8668 "Ext.grid.PropertyGrid"
8669 ]
8670 },
8671 "Ext.grid.property.HeaderContainer": {
8672 "idx": 541,
8673 "alias": [],
8674 "alternates": [
8675 "Ext.grid.PropertyColumnModel"
8676 ]
8677 },
8678 "Ext.grid.property.Property": {
8679 "idx": 542,
8680 "alias": [],
8681 "alternates": [
8682 "Ext.PropGridProperty"
8683 ]
8684 },
8685 "Ext.grid.property.Reader": {
8686 "idx": 543,
8687 "alias": [],
8688 "alternates": []
8689 },
8690 "Ext.grid.property.Store": {
8691 "idx": 544,
8692 "alias": [],
8693 "alternates": [
8694 "Ext.grid.PropertyStore"
8695 ]
8696 },
8697 "Ext.grid.selection.Cells": {
8698 "idx": 546,
8699 "alias": [],
8700 "alternates": []
8701 },
8702 "Ext.grid.selection.Columns": {
8703 "idx": 547,
8704 "alias": [],
8705 "alternates": []
8706 },
8707 "Ext.grid.selection.Replicator": {
8708 "idx": 548,
8709 "alias": [
8710 "plugin.selectionreplicator"
8711 ],
8712 "alternates": []
8713 },
8714 "Ext.grid.selection.Rows": {
8715 "idx": 549,
8716 "alias": [],
8717 "alternates": []
8718 },
8719 "Ext.grid.selection.Selection": {
8720 "idx": 545,
8721 "alias": [],
8722 "alternates": []
8723 },
8724 "Ext.grid.selection.SelectionExtender": {
8725 "idx": 550,
8726 "alias": [],
8727 "alternates": []
8728 },
8729 "Ext.grid.selection.SpreadsheetModel": {
8730 "idx": 551,
8731 "alias": [
8732 "selection.spreadsheet"
8733 ],
8734 "alternates": []
8735 },
8736 "Ext.layout.Context": {
8737 "idx": 554,
8738 "alias": [],
8739 "alternates": []
8740 },
8741 "Ext.layout.ContextItem": {
8742 "idx": 553,
8743 "alias": [],
8744 "alternates": []
8745 },
8746 "Ext.layout.Layout": {
8747 "idx": 330,
8748 "alias": [],
8749 "alternates": []
8750 },
8751 "Ext.layout.SizeModel": {
8752 "idx": 329,
8753 "alias": [],
8754 "alternates": []
8755 },
8756 "Ext.layout.component.Auto": {
8757 "idx": 342,
8758 "alias": [
8759 "layout.autocomponent"
8760 ],
8761 "alternates": []
8762 },
8763 "Ext.layout.component.Body": {
8764 "idx": 556,
8765 "alias": [
8766 "layout.body"
8767 ],
8768 "alternates": []
8769 },
8770 "Ext.layout.component.BoundList": {
8771 "idx": 447,
8772 "alias": [
8773 "layout.boundlist"
8774 ],
8775 "alternates": []
8776 },
8777 "Ext.layout.component.Component": {
8778 "idx": 341,
8779 "alias": [],
8780 "alternates": []
8781 },
8782 "Ext.layout.component.Dock": {
8783 "idx": 376,
8784 "alias": [
8785 "layout.dock"
8786 ],
8787 "alternates": [
8788 "Ext.layout.component.AbstractDock"
8789 ]
8790 },
8791 "Ext.layout.component.FieldSet": {
8792 "idx": 557,
8793 "alias": [
8794 "layout.fieldset"
8795 ],
8796 "alternates": []
8797 },
8798 "Ext.layout.component.ProgressBar": {
8799 "idx": 343,
8800 "alias": [
8801 "layout.progressbar"
8802 ],
8803 "alternates": []
8804 },
8805 "Ext.layout.component.field.FieldContainer": {
8806 "idx": 424,
8807 "alias": [
8808 "layout.fieldcontainer"
8809 ],
8810 "alternates": []
8811 },
8812 "Ext.layout.component.field.HtmlEditor": {
8813 "idx": 469,
8814 "alias": [
8815 "layout.htmleditor"
8816 ],
8817 "alternates": []
8818 },
8819 "Ext.layout.container.Absolute": {
8820 "idx": 558,
8821 "alias": [
8822 "layout.absolute"
8823 ],
8824 "alternates": [
8825 "Ext.layout.AbsoluteLayout"
8826 ]
8827 },
8828 "Ext.layout.container.Accordion": {
8829 "idx": 559,
8830 "alias": [
8831 "layout.accordion"
8832 ],
8833 "alternates": [
8834 "Ext.layout.AccordionLayout"
8835 ]
8836 },
8837 "Ext.layout.container.Anchor": {
8838 "idx": 386,
8839 "alias": [
8840 "layout.anchor"
8841 ],
8842 "alternates": [
8843 "Ext.layout.AnchorLayout"
8844 ]
8845 },
8846 "Ext.layout.container.Auto": {
8847 "idx": 332,
8848 "alias": [
8849 "layout.auto",
8850 "layout.autocontainer"
8851 ],
8852 "alternates": []
8853 },
8854 "Ext.layout.container.Border": {
8855 "idx": 561,
8856 "alias": [
8857 "layout.border"
8858 ],
8859 "alternates": [
8860 "Ext.layout.BorderLayout"
8861 ]
8862 },
8863 "Ext.layout.container.Box": {
8864 "idx": 365,
8865 "alias": [
8866 "layout.box"
8867 ],
8868 "alternates": [
8869 "Ext.layout.BoxLayout"
8870 ]
8871 },
8872 "Ext.layout.container.Card": {
8873 "idx": 562,
8874 "alias": [
8875 "layout.card"
8876 ],
8877 "alternates": [
8878 "Ext.layout.CardLayout"
8879 ]
8880 },
8881 "Ext.layout.container.Center": {
8882 "idx": 563,
8883 "alias": [
8884 "layout.center",
8885 "layout.ux.center"
8886 ],
8887 "alternates": [
8888 "Ext.ux.layout.Center"
8889 ]
8890 },
8891 "Ext.layout.container.CheckboxGroup": {
8892 "idx": 426,
8893 "alias": [
8894 "layout.checkboxgroup"
8895 ],
8896 "alternates": []
8897 },
8898 "Ext.layout.container.Column": {
8899 "idx": 389,
8900 "alias": [
8901 "layout.column"
8902 ],
8903 "alternates": [
8904 "Ext.layout.ColumnLayout"
8905 ]
8906 },
8907 "Ext.layout.container.ColumnSplitter": {
8908 "idx": 393,
8909 "alias": [
8910 "widget.columnsplitter"
8911 ],
8912 "alternates": []
8913 },
8914 "Ext.layout.container.ColumnSplitterTracker": {
8915 "idx": 392,
8916 "alias": [],
8917 "alternates": []
8918 },
8919 "Ext.layout.container.Container": {
8920 "idx": 331,
8921 "alias": [
8922 "layout.container"
8923 ],
8924 "alternates": [
8925 "Ext.layout.ContainerLayout"
8926 ]
8927 },
8928 "Ext.layout.container.Dashboard": {
8929 "idx": 394,
8930 "alias": [
8931 "layout.dashboard"
8932 ],
8933 "alternates": []
8934 },
8935 "Ext.layout.container.Editor": {
8936 "idx": 335,
8937 "alias": [
8938 "layout.editor"
8939 ],
8940 "alternates": []
8941 },
8942 "Ext.layout.container.Fit": {
8943 "idx": 480,
8944 "alias": [
8945 "layout.fit"
8946 ],
8947 "alternates": [
8948 "Ext.layout.FitLayout"
8949 ]
8950 },
8951 "Ext.layout.container.Form": {
8952 "idx": 564,
8953 "alias": [
8954 "layout.form"
8955 ],
8956 "alternates": [
8957 "Ext.layout.FormLayout"
8958 ]
8959 },
8960 "Ext.layout.container.HBox": {
8961 "idx": 366,
8962 "alias": [
8963 "layout.hbox"
8964 ],
8965 "alternates": [
8966 "Ext.layout.HBoxLayout"
8967 ]
8968 },
8969 "Ext.layout.container.SegmentedButton": {
8970 "idx": 352,
8971 "alias": [
8972 "layout.segmentedbutton"
8973 ],
8974 "alternates": []
8975 },
8976 "Ext.layout.container.Table": {
8977 "idx": 380,
8978 "alias": [
8979 "layout.table"
8980 ],
8981 "alternates": [
8982 "Ext.layout.TableLayout"
8983 ]
8984 },
8985 "Ext.layout.container.VBox": {
8986 "idx": 367,
8987 "alias": [
8988 "layout.vbox"
8989 ],
8990 "alternates": [
8991 "Ext.layout.VBoxLayout"
8992 ]
8993 },
8994 "Ext.layout.container.border.Region": {
8995 "idx": 120,
8996 "alias": [],
8997 "alternates": []
8998 },
8999 "Ext.layout.container.boxOverflow.Menu": {
9000 "idx": 471,
9001 "alias": [
9002 "box.overflow.Menu",
9003 "box.overflow.menu"
9004 ],
9005 "alternates": [
9006 "Ext.layout.boxOverflow.Menu"
9007 ]
9008 },
9009 "Ext.layout.container.boxOverflow.None": {
9010 "idx": 361,
9011 "alias": [
9012 "box.overflow.None",
9013 "box.overflow.none"
9014 ],
9015 "alternates": [
9016 "Ext.layout.boxOverflow.None"
9017 ]
9018 },
9019 "Ext.layout.container.boxOverflow.Scroller": {
9020 "idx": 362,
9021 "alias": [
9022 "box.overflow.Scroller",
9023 "box.overflow.scroller"
9024 ],
9025 "alternates": [
9026 "Ext.layout.boxOverflow.Scroller"
9027 ]
9028 },
9029 "Ext.list.AbstractTreeItem": {
9030 "idx": 303,
9031 "alias": [],
9032 "alternates": []
9033 },
9034 "Ext.list.RootTreeItem": {
9035 "idx": 304,
9036 "alias": [],
9037 "alternates": []
9038 },
9039 "Ext.list.Tree": {
9040 "idx": 306,
9041 "alias": [
9042 "widget.treelist"
9043 ],
9044 "alternates": []
9045 },
9046 "Ext.list.TreeItem": {
9047 "idx": 305,
9048 "alias": [
9049 "widget.treelistitem"
9050 ],
9051 "alternates": []
9052 },
9053 "Ext.menu.CheckItem": {
9054 "idx": 517,
9055 "alias": [
9056 "widget.menucheckitem"
9057 ],
9058 "alternates": []
9059 },
9060 "Ext.menu.ColorPicker": {
9061 "idx": 565,
9062 "alias": [
9063 "widget.colormenu"
9064 ],
9065 "alternates": []
9066 },
9067 "Ext.menu.DatePicker": {
9068 "idx": 566,
9069 "alias": [
9070 "widget.datemenu"
9071 ],
9072 "alternates": []
9073 },
9074 "Ext.menu.Item": {
9075 "idx": 516,
9076 "alias": [
9077 "widget.menuitem"
9078 ],
9079 "alternates": [
9080 "Ext.menu.TextItem"
9081 ]
9082 },
9083 "Ext.menu.Manager": {
9084 "idx": 347,
9085 "alias": [],
9086 "alternates": [
9087 "Ext.menu.MenuMgr"
9088 ]
9089 },
9090 "Ext.menu.Menu": {
9091 "idx": 519,
9092 "alias": [
9093 "widget.menu"
9094 ],
9095 "alternates": []
9096 },
9097 "Ext.menu.Separator": {
9098 "idx": 518,
9099 "alias": [
9100 "widget.menuseparator"
9101 ],
9102 "alternates": []
9103 },
9104 "Ext.mixin.Accessible": {
9105 "idx": 117,
9106 "alias": [],
9107 "alternates": []
9108 },
9109 "Ext.mixin.Bindable": {
9110 "idx": 79,
9111 "alias": [],
9112 "alternates": []
9113 },
9114 "Ext.mixin.ComponentDelegation": {
9115 "idx": 80,
9116 "alias": [],
9117 "alternates": []
9118 },
9119 "Ext.mixin.Container": {
9120 "idx": 307,
9121 "alias": [],
9122 "alternates": []
9123 },
9124 "Ext.mixin.Factoryable": {
9125 "idx": 12,
9126 "alias": [],
9127 "alternates": []
9128 },
9129 "Ext.mixin.Hookable": {
9130 "idx": 308,
9131 "alias": [],
9132 "alternates": []
9133 },
9134 "Ext.mixin.Identifiable": {
9135 "idx": 3,
9136 "alias": [],
9137 "alternates": []
9138 },
9139 "Ext.mixin.Inheritable": {
9140 "idx": 78,
9141 "alias": [],
9142 "alternates": []
9143 },
9144 "Ext.mixin.Mashup": {
9145 "idx": 309,
9146 "alias": [],
9147 "alternates": []
9148 },
9149 "Ext.mixin.Observable": {
9150 "idx": 4,
9151 "alias": [],
9152 "alternates": []
9153 },
9154 "Ext.mixin.Queryable": {
9155 "idx": 223,
9156 "alias": [],
9157 "alternates": []
9158 },
9159 "Ext.mixin.Responsive": {
9160 "idx": 310,
9161 "alias": [],
9162 "alternates": []
9163 },
9164 "Ext.mixin.Selectable": {
9165 "idx": 311,
9166 "alias": [],
9167 "alternates": []
9168 },
9169 "Ext.mixin.Templatable": {
9170 "idx": 38,
9171 "alias": [],
9172 "alternates": []
9173 },
9174 "Ext.mixin.Traversable": {
9175 "idx": 312,
9176 "alias": [],
9177 "alternates": []
9178 },
9179 "Ext.panel.Bar": {
9180 "idx": 354,
9181 "alias": [],
9182 "alternates": []
9183 },
9184 "Ext.panel.DD": {
9185 "idx": 375,
9186 "alias": [],
9187 "alternates": []
9188 },
9189 "Ext.panel.Header": {
9190 "idx": 360,
9191 "alias": [
9192 "widget.header"
9193 ],
9194 "alternates": []
9195 },
9196 "Ext.panel.Panel": {
9197 "idx": 379,
9198 "alias": [
9199 "widget.panel"
9200 ],
9201 "alternates": [
9202 "Ext.Panel"
9203 ]
9204 },
9205 "Ext.panel.Pinnable": {
9206 "idx": 567,
9207 "alias": [],
9208 "alternates": []
9209 },
9210 "Ext.panel.Proxy": {
9211 "idx": 374,
9212 "alias": [],
9213 "alternates": [
9214 "Ext.dd.PanelProxy"
9215 ]
9216 },
9217 "Ext.panel.Table": {
9218 "idx": 481,
9219 "alias": [
9220 "widget.tablepanel"
9221 ],
9222 "alternates": []
9223 },
9224 "Ext.panel.Title": {
9225 "idx": 355,
9226 "alias": [
9227 "widget.title"
9228 ],
9229 "alternates": []
9230 },
9231 "Ext.panel.Tool": {
9232 "idx": 356,
9233 "alias": [
9234 "widget.tool"
9235 ],
9236 "alternates": []
9237 },
9238 "Ext.perf.Accumulator": {
9239 "idx": 313,
9240 "alias": [],
9241 "alternates": []
9242 },
9243 "Ext.perf.Monitor": {
9244 "idx": 314,
9245 "alias": [],
9246 "alternates": [
9247 "Ext.Perf"
9248 ]
9249 },
9250 "Ext.picker.Color": {
9251 "idx": 468,
9252 "alias": [
9253 "widget.colorpicker"
9254 ],
9255 "alternates": [
9256 "Ext.ColorPalette"
9257 ]
9258 },
9259 "Ext.picker.Date": {
9260 "idx": 457,
9261 "alias": [
9262 "widget.datepicker"
9263 ],
9264 "alternates": [
9265 "Ext.DatePicker"
9266 ]
9267 },
9268 "Ext.picker.Month": {
9269 "idx": 456,
9270 "alias": [
9271 "widget.monthpicker"
9272 ],
9273 "alternates": [
9274 "Ext.MonthPicker"
9275 ]
9276 },
9277 "Ext.picker.Time": {
9278 "idx": 474,
9279 "alias": [
9280 "widget.timepicker"
9281 ],
9282 "alternates": []
9283 },
9284 "Ext.plugin.Abstract": {
9285 "idx": 315,
9286 "alias": [],
9287 "alternates": [
9288 "Ext.AbstractPlugin"
9289 ]
9290 },
9291 "Ext.plugin.AbstractClipboard": {
9292 "idx": 535,
9293 "alias": [],
9294 "alternates": []
9295 },
9296 "Ext.plugin.LazyItems": {
9297 "idx": 316,
9298 "alias": [
9299 "plugin.lazyitems"
9300 ],
9301 "alternates": []
9302 },
9303 "Ext.plugin.Manager": {
9304 "idx": 568,
9305 "alias": [],
9306 "alternates": [
9307 "Ext.PluginManager",
9308 "Ext.PluginMgr"
9309 ]
9310 },
9311 "Ext.plugin.Responsive": {
9312 "idx": 383,
9313 "alias": [
9314 "plugin.responsive"
9315 ],
9316 "alternates": []
9317 },
9318 "Ext.plugin.Viewport": {
9319 "idx": 384,
9320 "alias": [
9321 "plugin.viewport"
9322 ],
9323 "alternates": []
9324 },
9325 "Ext.promise.Consequence": {
9326 "idx": 7,
9327 "alias": [],
9328 "alternates": []
9329 },
9330 "Ext.promise.Deferred": {
9331 "idx": 8,
9332 "alias": [],
9333 "alternates": []
9334 },
9335 "Ext.promise.Promise": {
9336 "idx": 9,
9337 "alias": [],
9338 "alternates": []
9339 },
9340 "Ext.resizer.BorderSplitter": {
9341 "idx": 560,
9342 "alias": [
9343 "widget.bordersplitter"
9344 ],
9345 "alternates": []
9346 },
9347 "Ext.resizer.BorderSplitterTracker": {
9348 "idx": 569,
9349 "alias": [],
9350 "alternates": []
9351 },
9352 "Ext.resizer.Handle": {
9353 "idx": 570,
9354 "alias": [],
9355 "alternates": []
9356 },
9357 "Ext.resizer.ResizeTracker": {
9358 "idx": 571,
9359 "alias": [],
9360 "alternates": []
9361 },
9362 "Ext.resizer.Resizer": {
9363 "idx": 572,
9364 "alias": [],
9365 "alternates": [
9366 "Ext.Resizable"
9367 ]
9368 },
9369 "Ext.resizer.Splitter": {
9370 "idx": 364,
9371 "alias": [
9372 "widget.splitter"
9373 ],
9374 "alternates": []
9375 },
9376 "Ext.resizer.SplitterTracker": {
9377 "idx": 391,
9378 "alias": [],
9379 "alternates": []
9380 },
9381 "Ext.scroll.DomScroller": {
9382 "idx": 109,
9383 "alias": [
9384 "scroller.dom"
9385 ],
9386 "alternates": []
9387 },
9388 "Ext.scroll.Indicator": {
9389 "idx": 107,
9390 "alias": [
9391 "widget.scrollindicator"
9392 ],
9393 "alternates": []
9394 },
9395 "Ext.scroll.Scroller": {
9396 "idx": 93,
9397 "alias": [
9398 "scroller.scroller"
9399 ],
9400 "alternates": []
9401 },
9402 "Ext.scroll.TouchScroller": {
9403 "idx": 108,
9404 "alias": [
9405 "scroller.touch"
9406 ],
9407 "alternates": []
9408 },
9409 "Ext.selection.CellModel": {
9410 "idx": 573,
9411 "alias": [
9412 "selection.cellmodel"
9413 ],
9414 "alternates": []
9415 },
9416 "Ext.selection.CheckboxModel": {
9417 "idx": 575,
9418 "alias": [
9419 "selection.checkboxmodel"
9420 ],
9421 "alternates": []
9422 },
9423 "Ext.selection.DataViewModel": {
9424 "idx": 442,
9425 "alias": [
9426 "selection.dataviewmodel"
9427 ],
9428 "alternates": []
9429 },
9430 "Ext.selection.Model": {
9431 "idx": 441,
9432 "alias": [
9433 "selection.abstract"
9434 ],
9435 "alternates": [
9436 "Ext.AbstractSelectionModel"
9437 ]
9438 },
9439 "Ext.selection.RowModel": {
9440 "idx": 574,
9441 "alias": [
9442 "selection.rowmodel"
9443 ],
9444 "alternates": []
9445 },
9446 "Ext.selection.TreeModel": {
9447 "idx": 576,
9448 "alias": [
9449 "selection.treemodel"
9450 ],
9451 "alternates": []
9452 },
9453 "Ext.slider.Multi": {
9454 "idx": 579,
9455 "alias": [
9456 "widget.multislider"
9457 ],
9458 "alternates": [
9459 "Ext.slider.MultiSlider"
9460 ]
9461 },
9462 "Ext.slider.Single": {
9463 "idx": 580,
9464 "alias": [
9465 "widget.slider",
9466 "widget.sliderfield"
9467 ],
9468 "alternates": [
9469 "Ext.Slider",
9470 "Ext.form.SliderField",
9471 "Ext.slider.SingleSlider",
9472 "Ext.slider.Slider"
9473 ]
9474 },
9475 "Ext.slider.Thumb": {
9476 "idx": 577,
9477 "alias": [],
9478 "alternates": []
9479 },
9480 "Ext.slider.Tip": {
9481 "idx": 578,
9482 "alias": [
9483 "widget.slidertip"
9484 ],
9485 "alternates": []
9486 },
9487 "Ext.slider.Widget": {
9488 "idx": 581,
9489 "alias": [
9490 "widget.sliderwidget"
9491 ],
9492 "alternates": []
9493 },
9494 "Ext.sparkline.Bar": {
9495 "idx": 589,
9496 "alias": [
9497 "widget.sparklinebar"
9498 ],
9499 "alternates": []
9500 },
9501 "Ext.sparkline.BarBase": {
9502 "idx": 587,
9503 "alias": [],
9504 "alternates": []
9505 },
9506 "Ext.sparkline.Base": {
9507 "idx": 586,
9508 "alias": [],
9509 "alternates": []
9510 },
9511 "Ext.sparkline.Box": {
9512 "idx": 590,
9513 "alias": [
9514 "widget.sparklinebox"
9515 ],
9516 "alternates": []
9517 },
9518 "Ext.sparkline.Bullet": {
9519 "idx": 591,
9520 "alias": [
9521 "widget.sparklinebullet"
9522 ],
9523 "alternates": []
9524 },
9525 "Ext.sparkline.CanvasBase": {
9526 "idx": 583,
9527 "alias": [],
9528 "alternates": []
9529 },
9530 "Ext.sparkline.CanvasCanvas": {
9531 "idx": 584,
9532 "alias": [],
9533 "alternates": []
9534 },
9535 "Ext.sparkline.Discrete": {
9536 "idx": 592,
9537 "alias": [
9538 "widget.sparklinediscrete"
9539 ],
9540 "alternates": []
9541 },
9542 "Ext.sparkline.Line": {
9543 "idx": 593,
9544 "alias": [
9545 "widget.sparklineline"
9546 ],
9547 "alternates": []
9548 },
9549 "Ext.sparkline.Pie": {
9550 "idx": 594,
9551 "alias": [
9552 "widget.sparklinepie"
9553 ],
9554 "alternates": []
9555 },
9556 "Ext.sparkline.RangeMap": {
9557 "idx": 588,
9558 "alias": [],
9559 "alternates": []
9560 },
9561 "Ext.sparkline.Shape": {
9562 "idx": 582,
9563 "alias": [],
9564 "alternates": []
9565 },
9566 "Ext.sparkline.TriState": {
9567 "idx": 595,
9568 "alias": [
9569 "widget.sparklinetristate"
9570 ],
9571 "alternates": []
9572 },
9573 "Ext.sparkline.VmlCanvas": {
9574 "idx": 585,
9575 "alias": [],
9576 "alternates": []
9577 },
9578 "Ext.state.CookieProvider": {
9579 "idx": 596,
9580 "alias": [],
9581 "alternates": []
9582 },
9583 "Ext.state.LocalStorageProvider": {
9584 "idx": 597,
9585 "alias": [
9586 "state.localstorage"
9587 ],
9588 "alternates": []
9589 },
9590 "Ext.state.Manager": {
9591 "idx": 114,
9592 "alias": [],
9593 "alternates": []
9594 },
9595 "Ext.state.Provider": {
9596 "idx": 113,
9597 "alias": [],
9598 "alternates": []
9599 },
9600 "Ext.state.Stateful": {
9601 "idx": 115,
9602 "alias": [],
9603 "alternates": []
9604 },
9605 "Ext.tab.Bar": {
9606 "idx": 599,
9607 "alias": [
9608 "widget.tabbar"
9609 ],
9610 "alternates": []
9611 },
9612 "Ext.tab.Panel": {
9613 "idx": 600,
9614 "alias": [
9615 "widget.tabpanel"
9616 ],
9617 "alternates": [
9618 "Ext.TabPanel"
9619 ]
9620 },
9621 "Ext.tab.Tab": {
9622 "idx": 598,
9623 "alias": [
9624 "widget.tab"
9625 ],
9626 "alternates": []
9627 },
9628 "Ext.tip.QuickTip": {
9629 "idx": 466,
9630 "alias": [
9631 "widget.quicktip"
9632 ],
9633 "alternates": [
9634 "Ext.QuickTip"
9635 ]
9636 },
9637 "Ext.tip.QuickTipManager": {
9638 "idx": 467,
9639 "alias": [],
9640 "alternates": [
9641 "Ext.QuickTips"
9642 ]
9643 },
9644 "Ext.tip.Tip": {
9645 "idx": 464,
9646 "alias": [
9647 "widget.tip"
9648 ],
9649 "alternates": [
9650 "Ext.Tip"
9651 ]
9652 },
9653 "Ext.tip.ToolTip": {
9654 "idx": 465,
9655 "alias": [
9656 "widget.tooltip"
9657 ],
9658 "alternates": [
9659 "Ext.ToolTip"
9660 ]
9661 },
9662 "Ext.toolbar.Breadcrumb": {
9663 "idx": 601,
9664 "alias": [
9665 "widget.breadcrumb"
9666 ],
9667 "alternates": []
9668 },
9669 "Ext.toolbar.Fill": {
9670 "idx": 602,
9671 "alias": [
9672 "widget.tbfill"
9673 ],
9674 "alternates": [
9675 "Ext.Toolbar.Fill"
9676 ]
9677 },
9678 "Ext.toolbar.Item": {
9679 "idx": 448,
9680 "alias": [
9681 "widget.tbitem"
9682 ],
9683 "alternates": [
9684 "Ext.Toolbar.Item"
9685 ]
9686 },
9687 "Ext.toolbar.Paging": {
9688 "idx": 453,
9689 "alias": [
9690 "widget.pagingtoolbar"
9691 ],
9692 "alternates": [
9693 "Ext.PagingToolbar"
9694 ]
9695 },
9696 "Ext.toolbar.Separator": {
9697 "idx": 470,
9698 "alias": [
9699 "widget.tbseparator"
9700 ],
9701 "alternates": [
9702 "Ext.Toolbar.Separator"
9703 ]
9704 },
9705 "Ext.toolbar.Spacer": {
9706 "idx": 603,
9707 "alias": [
9708 "widget.tbspacer"
9709 ],
9710 "alternates": [
9711 "Ext.Toolbar.Spacer"
9712 ]
9713 },
9714 "Ext.toolbar.TextItem": {
9715 "idx": 449,
9716 "alias": [
9717 "widget.tbtext"
9718 ],
9719 "alternates": [
9720 "Ext.Toolbar.TextItem"
9721 ]
9722 },
9723 "Ext.toolbar.Toolbar": {
9724 "idx": 368,
9725 "alias": [
9726 "widget.toolbar"
9727 ],
9728 "alternates": [
9729 "Ext.Toolbar"
9730 ]
9731 },
9732 "Ext.tree.Column": {
9733 "idx": 604,
9734 "alias": [
9735 "widget.treecolumn"
9736 ],
9737 "alternates": []
9738 },
9739 "Ext.tree.NavigationModel": {
9740 "idx": 605,
9741 "alias": [
9742 "view.navigation.tree"
9743 ],
9744 "alternates": []
9745 },
9746 "Ext.tree.Panel": {
9747 "idx": 607,
9748 "alias": [
9749 "widget.treepanel"
9750 ],
9751 "alternates": [
9752 "Ext.tree.TreePanel",
9753 "Ext.TreePanel"
9754 ]
9755 },
9756 "Ext.tree.View": {
9757 "idx": 606,
9758 "alias": [
9759 "widget.treeview"
9760 ],
9761 "alternates": []
9762 },
9763 "Ext.tree.ViewDragZone": {
9764 "idx": 609,
9765 "alias": [],
9766 "alternates": []
9767 },
9768 "Ext.tree.ViewDropZone": {
9769 "idx": 610,
9770 "alias": [],
9771 "alternates": []
9772 },
9773 "Ext.tree.plugin.TreeViewDragDrop": {
9774 "idx": 611,
9775 "alias": [
9776 "plugin.treeviewdragdrop"
9777 ],
9778 "alternates": []
9779 },
9780 "Ext.util.AbstractMixedCollection": {
9781 "idx": 52,
9782 "alias": [],
9783 "alternates": []
9784 },
9785 "Ext.util.Animate": {
9786 "idx": 73,
9787 "alias": [],
9788 "alternates": []
9789 },
9790 "Ext.util.Bag": {
9791 "idx": 186,
9792 "alias": [],
9793 "alternates": []
9794 },
9795 "Ext.util.Base64": {
9796 "idx": 317,
9797 "alias": [],
9798 "alternates": []
9799 },
9800 "Ext.util.CSS": {
9801 "idx": 612,
9802 "alias": [],
9803 "alternates": []
9804 },
9805 "Ext.util.CSV": {
9806 "idx": 319,
9807 "alias": [],
9808 "alternates": []
9809 },
9810 "Ext.util.ClickRepeater": {
9811 "idx": 348,
9812 "alias": [],
9813 "alternates": []
9814 },
9815 "Ext.util.Collection": {
9816 "idx": 127,
9817 "alias": [],
9818 "alternates": []
9819 },
9820 "Ext.util.CollectionKey": {
9821 "idx": 125,
9822 "alias": [],
9823 "alternates": []
9824 },
9825 "Ext.util.ComponentDragger": {
9826 "idx": 411,
9827 "alias": [],
9828 "alternates": []
9829 },
9830 "Ext.util.Cookies": {
9831 "idx": 613,
9832 "alias": [],
9833 "alternates": []
9834 },
9835 "Ext.util.DelimitedValue": {
9836 "idx": 318,
9837 "alias": [],
9838 "alternates": []
9839 },
9840 "Ext.util.ElementContainer": {
9841 "idx": 111,
9842 "alias": [],
9843 "alternates": []
9844 },
9845 "Ext.util.Event": {
9846 "idx": 2,
9847 "alias": [],
9848 "alternates": []
9849 },
9850 "Ext.util.Filter": {
9851 "idx": 50,
9852 "alias": [],
9853 "alternates": []
9854 },
9855 "Ext.util.FilterCollection": {
9856 "idx": 170,
9857 "alias": [],
9858 "alternates": []
9859 },
9860 "Ext.util.Floating": {
9861 "idx": 110,
9862 "alias": [],
9863 "alternates": []
9864 },
9865 "Ext.util.FocusTrap": {
9866 "idx": 412,
9867 "alias": [],
9868 "alternates": []
9869 },
9870 "Ext.util.Focusable": {
9871 "idx": 116,
9872 "alias": [],
9873 "alternates": []
9874 },
9875 "Ext.util.FocusableContainer": {
9876 "idx": 359,
9877 "alias": [],
9878 "alternates": []
9879 },
9880 "Ext.util.Format": {
9881 "idx": 84,
9882 "alias": [],
9883 "alternates": []
9884 },
9885 "Ext.util.Group": {
9886 "idx": 168,
9887 "alias": [],
9888 "alternates": []
9889 },
9890 "Ext.util.GroupCollection": {
9891 "idx": 171,
9892 "alias": [],
9893 "alternates": []
9894 },
9895 "Ext.util.Grouper": {
9896 "idx": 126,
9897 "alias": [],
9898 "alternates": []
9899 },
9900 "Ext.util.HashMap": {
9901 "idx": 5,
9902 "alias": [],
9903 "alternates": []
9904 },
9905 "Ext.util.History": {
9906 "idx": 179,
9907 "alias": [],
9908 "alternates": [
9909 "Ext.History"
9910 ]
9911 },
9912 "Ext.util.Inflector": {
9913 "idx": 134,
9914 "alias": [],
9915 "alternates": []
9916 },
9917 "Ext.util.ItemCollection": {
9918 "idx": 320,
9919 "alias": [],
9920 "alternates": [
9921 "Ext.ItemCollection"
9922 ]
9923 },
9924 "Ext.util.KeyMap": {
9925 "idx": 357,
9926 "alias": [],
9927 "alternates": [
9928 "Ext.KeyMap"
9929 ]
9930 },
9931 "Ext.util.KeyNav": {
9932 "idx": 358,
9933 "alias": [],
9934 "alternates": [
9935 "Ext.KeyNav"
9936 ]
9937 },
9938 "Ext.util.KeyboardInteractive": {
9939 "idx": 118,
9940 "alias": [],
9941 "alternates": []
9942 },
9943 "Ext.util.LocalStorage": {
9944 "idx": 321,
9945 "alias": [],
9946 "alternates": []
9947 },
9948 "Ext.util.LruCache": {
9949 "idx": 22,
9950 "alias": [],
9951 "alternates": []
9952 },
9953 "Ext.util.Memento": {
9954 "idx": 377,
9955 "alias": [],
9956 "alternates": []
9957 },
9958 "Ext.util.MixedCollection": {
9959 "idx": 55,
9960 "alias": [],
9961 "alternates": []
9962 },
9963 "Ext.util.ObjectTemplate": {
9964 "idx": 128,
9965 "alias": [],
9966 "alternates": []
9967 },
9968 "Ext.util.Observable": {
9969 "idx": 51,
9970 "alias": [],
9971 "alternates": []
9972 },
9973 "Ext.util.Offset": {
9974 "idx": 32,
9975 "alias": [],
9976 "alternates": []
9977 },
9978 "Ext.util.PaintMonitor": {
9979 "idx": 47,
9980 "alias": [],
9981 "alternates": []
9982 },
9983 "Ext.util.Point": {
9984 "idx": 34,
9985 "alias": [],
9986 "alternates": []
9987 },
9988 "Ext.util.Positionable": {
9989 "idx": 25,
9990 "alias": [],
9991 "alternates": []
9992 },
9993 "Ext.util.ProtoElement": {
9994 "idx": 91,
9995 "alias": [],
9996 "alternates": []
9997 },
9998 "Ext.util.Queue": {
9999 "idx": 552,
10000 "alias": [],
10001 "alternates": []
10002 },
10003 "Ext.util.Region": {
10004 "idx": 33,
10005 "alias": [],
10006 "alternates": []
10007 },
10008 "Ext.util.Renderable": {
10009 "idx": 112,
10010 "alias": [],
10011 "alternates": []
10012 },
10013 "Ext.util.Schedulable": {
10014 "idx": 196,
10015 "alias": [],
10016 "alternates": []
10017 },
10018 "Ext.util.Scheduler": {
10019 "idx": 187,
10020 "alias": [],
10021 "alternates": []
10022 },
10023 "Ext.util.SizeMonitor": {
10024 "idx": 43,
10025 "alias": [],
10026 "alternates": []
10027 },
10028 "Ext.util.Sortable": {
10029 "idx": 54,
10030 "alias": [],
10031 "alternates": []
10032 },
10033 "Ext.util.Sorter": {
10034 "idx": 53,
10035 "alias": [],
10036 "alternates": []
10037 },
10038 "Ext.util.SorterCollection": {
10039 "idx": 169,
10040 "alias": [],
10041 "alternates": []
10042 },
10043 "Ext.util.StoreHolder": {
10044 "idx": 339,
10045 "alias": [],
10046 "alternates": []
10047 },
10048 "Ext.util.TSV": {
10049 "idx": 322,
10050 "alias": [],
10051 "alternates": []
10052 },
10053 "Ext.util.TaskManager": {
10054 "idx": 323,
10055 "alias": [],
10056 "alternates": [
10057 "Ext.TaskManager"
10058 ]
10059 },
10060 "Ext.util.TaskRunner": {
10061 "idx": 56,
10062 "alias": [],
10063 "alternates": []
10064 },
10065 "Ext.util.TextMetrics": {
10066 "idx": 324,
10067 "alias": [],
10068 "alternates": []
10069 },
10070 "Ext.util.Translatable": {
10071 "idx": 106,
10072 "alias": [],
10073 "alternates": []
10074 },
10075 "Ext.util.XTemplateCompiler": {
10076 "idx": 87,
10077 "alias": [],
10078 "alternates": []
10079 },
10080 "Ext.util.XTemplateParser": {
10081 "idx": 86,
10082 "alias": [],
10083 "alternates": []
10084 },
10085 "Ext.util.paintmonitor.Abstract": {
10086 "idx": 45,
10087 "alias": [],
10088 "alternates": []
10089 },
10090 "Ext.util.paintmonitor.CssAnimation": {
10091 "idx": 46,
10092 "alias": [],
10093 "alternates": []
10094 },
10095 "Ext.util.paintmonitor.OverflowChange": {
10096 "idx": 325,
10097 "alias": [],
10098 "alternates": []
10099 },
10100 "Ext.util.sizemonitor.Abstract": {
10101 "idx": 40,
10102 "alias": [],
10103 "alternates": []
10104 },
10105 "Ext.util.sizemonitor.OverflowChange": {
10106 "idx": 42,
10107 "alias": [],
10108 "alternates": []
10109 },
10110 "Ext.util.sizemonitor.Scroll": {
10111 "idx": 41,
10112 "alias": [],
10113 "alternates": []
10114 },
10115 "Ext.util.translatable.Abstract": {
10116 "idx": 100,
10117 "alias": [],
10118 "alternates": []
10119 },
10120 "Ext.util.translatable.CssPosition": {
10121 "idx": 105,
10122 "alias": [],
10123 "alternates": []
10124 },
10125 "Ext.util.translatable.CssTransform": {
10126 "idx": 102,
10127 "alias": [],
10128 "alternates": []
10129 },
10130 "Ext.util.translatable.Dom": {
10131 "idx": 101,
10132 "alias": [],
10133 "alternates": []
10134 },
10135 "Ext.util.translatable.ScrollParent": {
10136 "idx": 104,
10137 "alias": [],
10138 "alternates": []
10139 },
10140 "Ext.util.translatable.ScrollPosition": {
10141 "idx": 103,
10142 "alias": [],
10143 "alternates": []
10144 },
10145 "Ext.view.AbstractView": {
10146 "idx": 444,
10147 "alias": [],
10148 "alternates": []
10149 },
10150 "Ext.view.BoundList": {
10151 "idx": 454,
10152 "alias": [
10153 "widget.boundlist"
10154 ],
10155 "alternates": [
10156 "Ext.BoundList"
10157 ]
10158 },
10159 "Ext.view.BoundListKeyNav": {
10160 "idx": 446,
10161 "alias": [
10162 "view.navigation.boundlist"
10163 ],
10164 "alternates": []
10165 },
10166 "Ext.view.DragZone": {
10167 "idx": 608,
10168 "alias": [],
10169 "alternates": []
10170 },
10171 "Ext.view.DropZone": {
10172 "idx": 493,
10173 "alias": [],
10174 "alternates": []
10175 },
10176 "Ext.view.MultiSelector": {
10177 "idx": 615,
10178 "alias": [
10179 "widget.multiselector"
10180 ],
10181 "alternates": []
10182 },
10183 "Ext.view.MultiSelectorSearch": {
10184 "idx": 614,
10185 "alias": [
10186 "widget.multiselector-search"
10187 ],
10188 "alternates": []
10189 },
10190 "Ext.view.NavigationModel": {
10191 "idx": 443,
10192 "alias": [
10193 "view.navigation.default"
10194 ],
10195 "alternates": []
10196 },
10197 "Ext.view.NodeCache": {
10198 "idx": 487,
10199 "alias": [],
10200 "alternates": []
10201 },
10202 "Ext.view.Table": {
10203 "idx": 488,
10204 "alias": [
10205 "widget.gridview",
10206 "widget.tableview"
10207 ],
10208 "alternates": [
10209 "Ext.grid.View"
10210 ]
10211 },
10212 "Ext.view.TableLayout": {
10213 "idx": 485,
10214 "alias": [
10215 "layout.tableview"
10216 ],
10217 "alternates": []
10218 },
10219 "Ext.view.View": {
10220 "idx": 445,
10221 "alias": [
10222 "widget.dataview"
10223 ],
10224 "alternates": [
10225 "Ext.DataView"
10226 ]
10227 },
10228 "Ext.window.MessageBox": {
10229 "idx": 421,
10230 "alias": [
10231 "widget.messagebox"
10232 ],
10233 "alternates": []
10234 },
10235 "Ext.window.Toast": {
10236 "idx": 616,
10237 "alias": [
10238 "widget.toast"
10239 ],
10240 "alternates": []
10241 },
10242 "Ext.window.Window": {
10243 "idx": 413,
10244 "alias": [
10245 "widget.window"
10246 ],
10247 "alternates": [
10248 "Ext.Window"
10249 ]
10250 }
10251 },
10252 "packages": {
10253 "classic": {
10254 "build": {
10255 "dir": "${package.output}"
10256 },
10257 "creator": "Sencha",
10258 "namespace": "Ext",
10259 "requires": [
10260 "ext",
10261 "core",
10262 "classic"
10263 ],
10264 "type": "toolkit",
10265 "version": "6.0.1.250"
10266 },
10267 "cmd": {
10268 "version": "6.0.1.75"
10269 },
10270 "core": {
10271 "alternateName": [
10272 "sencha-core"
10273 ],
10274 "creator": "Sencha",
10275 "requires": [
10276 "ext"
10277 ],
10278 "type": "code",
10279 "version": "6.0.1.250"
10280 },
10281 "ext": {
10282 "build": {
10283 "dir": "${package.output.base}"
10284 },
10285 "creator": "Sencha",
10286 "license": "gpl",
10287 "namespace": "Ext",
10288 "requires": [],
10289 "resource": {
10290 "paths": [
10291 "resources"
10292 ]
10293 },
10294 "type": "framework",
10295 "version": "6.0.1.250"
10296 }
10297 },
10298 "bootRelative": true
10299});\r
10300// @tag core\r
10301// @define Ext.Boot\r
10302var Ext = Ext || {};\r
10303//<editor-fold desc="Boot">\r
10304/*
10305 * @class Ext.Boot
10306 * @singleton
10307 */\r
10308Ext.Boot = Ext.Boot || (function(emptyFn) {\r
10309 var doc = document,\r
10310 _emptyArray = [],\r
10311 _config = {\r
10312 /*
10313 * @cfg {Boolean} [disableCaching=true]
10314 * If `true` current timestamp is added to script URL's to prevent caching.
10315 * In debug builds, adding a "cache" or "disableCacheBuster" query parameter
10316 * to the page's URL will set this to `false`.
10317 */\r
10318 disableCaching: (/[?&](?:cache|disableCacheBuster)\b/i.test(location.search) || !(/http[s]?\:/i.test(location.href)) || /(^|[ ;])ext-cache=1/.test(doc.cookie)) ? false : true,\r
10319 /*
10320 * @cfg {String} [disableCachingParam="_dc"]
10321 * The query parameter name for the cache buster's timestamp.
10322 */\r
10323 disableCachingParam: '_dc',\r
10324 /*
10325 * @cfg {Boolean} loadDelay
10326 * Millisecond delay between asynchronous script injection (prevents stack
10327 * overflow on some user agents) 'false' disables delay but potentially
10328 * increases stack load.
10329 */\r
10330 loadDelay: false,\r
10331 /*
10332 * @cfg {Boolean} preserveScripts
10333 * `false` to remove asynchronously loaded scripts, `true` to retain script
10334 * element for browser debugger compatibility and improved load performance.
10335 */\r
10336 preserveScripts: true,\r
10337 /*
10338 * @cfg {String} [charset=UTF-8]
10339 * Optional charset to specify encoding of dynamic content.
10340 */\r
10341 charset: 'UTF-8'\r
10342 },\r
10343 _assetConfig = {},\r
10344 cssRe = /\.css(?:\?|$)/i,\r
10345 resolverEl = doc.createElement('a'),\r
10346 isBrowser = typeof window !== 'undefined',\r
10347 _environment = {\r
10348 browser: isBrowser,\r
10349 node: !isBrowser && (typeof require === 'function'),\r
10350 phantom: (window && (window._phantom || window.callPhantom)) || /PhantomJS/.test(window.navigator.userAgent)\r
10351 },\r
10352 _tags = (Ext.platformTags = {}),\r
10353 _debug = function(message) {},\r
10354 //console.log(message);\r
10355 _apply = function(object, config, defaults) {\r
10356 if (defaults) {\r
10357 _apply(object, defaults);\r
10358 }\r
10359 if (object && config && typeof config === 'object') {\r
10360 for (var i in config) {\r
10361 object[i] = config[i];\r
10362 }\r
10363 }\r
10364 return object;\r
10365 },\r
10366 _merge = function() {\r
10367 var lowerCase = false,\r
10368 obj = Array.prototype.shift.call(arguments),\r
10369 index, i, len, value;\r
10370 if (typeof arguments[arguments.length - 1] === 'boolean') {\r
10371 lowerCase = Array.prototype.pop.call(arguments);\r
10372 }\r
10373 len = arguments.length;\r
10374 for (index = 0; index < len; index++) {\r
10375 value = arguments[index];\r
10376 if (typeof value === 'object') {\r
10377 for (i in value) {\r
10378 obj[lowerCase ? i.toLowerCase() : i] = value[i];\r
10379 }\r
10380 }\r
10381 }\r
10382 return obj;\r
10383 },\r
10384 _getKeys = (typeof Object.keys == 'function') ? function(object) {\r
10385 if (!object) {\r
10386 return [];\r
10387 }\r
10388 return Object.keys(object);\r
10389 } : function(object) {\r
10390 var keys = [],\r
10391 property;\r
10392 for (property in object) {\r
10393 if (object.hasOwnProperty(property)) {\r
10394 keys.push(property);\r
10395 }\r
10396 }\r
10397 return keys;\r
10398 },\r
10399 /*
10400 * The Boot loader class manages Request objects that contain one or
10401 * more individual urls that need to be loaded. Requests can be performed
10402 * synchronously or asynchronously, but will always evaluate urls in the
10403 * order specified on the request object.
10404 */\r
10405 Boot = {\r
10406 loading: 0,\r
10407 loaded: 0,\r
10408 apply: _apply,\r
10409 env: _environment,\r
10410 config: _config,\r
10411 /**
10412 * @cfg {Object} assetConfig
10413 * A map (url->assetConfig) that contains information about assets loaded by the Microlaoder.
10414 */\r
10415 assetConfig: _assetConfig,\r
10416 // Keyed by absolute URL this object holds "true" if that URL is already loaded\r
10417 // or an array of callbacks to call once it loads.\r
10418 scripts: {},\r
10419 /*
10420 Entry objects
10421
10422 'http://foo.com/bar/baz/Thing.js': {
10423 done: true,
10424 el: scriptEl || linkEl,
10425 preserve: true,
10426 requests: [ request1, ... ]
10427 }
10428 */\r
10429 /*
10430 * contains the current script name being loaded
10431 * (loadSync or sequential load only)
10432 */\r
10433 currentFile: null,\r
10434 suspendedQueue: [],\r
10435 currentRequest: null,\r
10436 // when loadSync is called, need to cause subsequent load requests to also be loadSync,\r
10437 // eg, when Ext.require(...) is called\r
10438 syncMode: false,\r
10439 /*
10440 * simple helper method for debugging
10441 */\r
10442 debug: _debug,\r
10443 /*
10444 * enables / disables loading scripts via script / link elements rather
10445 * than using ajax / eval
10446 */\r
10447 useElements: true,\r
10448 listeners: [],\r
10449 Request: Request,\r
10450 Entry: Entry,\r
10451 allowMultipleBrowsers: false,\r
10452 browserNames: {\r
10453 ie: 'IE',\r
10454 firefox: 'Firefox',\r
10455 safari: 'Safari',\r
10456 chrome: 'Chrome',\r
10457 opera: 'Opera',\r
10458 dolfin: 'Dolfin',\r
10459 edge: 'Edge',\r
10460 webosbrowser: 'webOSBrowser',\r
10461 chromeMobile: 'ChromeMobile',\r
10462 chromeiOS: 'ChromeiOS',\r
10463 silk: 'Silk',\r
10464 other: 'Other'\r
10465 },\r
10466 osNames: {\r
10467 ios: 'iOS',\r
10468 android: 'Android',\r
10469 windowsPhone: 'WindowsPhone',\r
10470 webos: 'webOS',\r
10471 blackberry: 'BlackBerry',\r
10472 rimTablet: 'RIMTablet',\r
10473 mac: 'MacOS',\r
10474 win: 'Windows',\r
10475 tizen: 'Tizen',\r
10476 linux: 'Linux',\r
10477 bada: 'Bada',\r
10478 chromeOS: 'ChromeOS',\r
10479 other: 'Other'\r
10480 },\r
10481 browserPrefixes: {\r
10482 ie: 'MSIE ',\r
10483 edge: 'Edge/',\r
10484 firefox: 'Firefox/',\r
10485 chrome: 'Chrome/',\r
10486 safari: 'Version/',\r
10487 opera: 'OPR/',\r
10488 dolfin: 'Dolfin/',\r
10489 webosbrowser: 'wOSBrowser/',\r
10490 chromeMobile: 'CrMo/',\r
10491 chromeiOS: 'CriOS/',\r
10492 silk: 'Silk/'\r
10493 },\r
10494 // When a UA reports multiple browsers this list is used to prioritize the 'real' browser\r
10495 // lower index number will win\r
10496 browserPriority: [\r
10497 'edge',\r
10498 'opera',\r
10499 'dolfin',\r
10500 'webosbrowser',\r
10501 'silk',\r
10502 'chromeiOS',\r
10503 'chromeMobile',\r
10504 'ie',\r
10505 'firefox',\r
10506 'safari',\r
10507 'chrome'\r
10508 ],\r
10509 osPrefixes: {\r
10510 tizen: '(Tizen )',\r
10511 ios: 'i(?:Pad|Phone|Pod)(?:.*)CPU(?: iPhone)? OS ',\r
10512 android: '(Android |HTC_|Silk/)',\r
10513 // Some HTC devices ship with an OSX userAgent by default,\r
10514 // so we need to add a direct check for HTC_\r
10515 windowsPhone: 'Windows Phone ',\r
10516 blackberry: '(?:BlackBerry|BB)(?:.*)Version/',\r
10517 rimTablet: 'RIM Tablet OS ',\r
10518 webos: '(?:webOS|hpwOS)/',\r
10519 bada: 'Bada/',\r
10520 chromeOS: 'CrOS '\r
10521 },\r
10522 fallbackOSPrefixes: {\r
10523 windows: 'win',\r
10524 mac: 'mac',\r
10525 linux: 'linux'\r
10526 },\r
10527 devicePrefixes: {\r
10528 iPhone: 'iPhone',\r
10529 iPod: 'iPod',\r
10530 iPad: 'iPad'\r
10531 },\r
10532 maxIEVersion: 12,\r
10533 /**
10534 * The default function that detects various platforms and sets tags
10535 * in the platform map accordingly. Examples are iOS, android, tablet, etc.
10536 * @param tags the set of tags to populate
10537 */\r
10538 detectPlatformTags: function() {\r
10539 var me = this,\r
10540 ua = navigator.userAgent,\r
10541 isMobile = /Mobile(\/|\s)/.test(ua),\r
10542 element = document.createElement('div'),\r
10543 isEventSupported = function(name, tag) {\r
10544 if (tag === undefined) {\r
10545 tag = window;\r
10546 }\r
10547 var eventName = 'on' + name.toLowerCase(),\r
10548 isSupported = (eventName in element);\r
10549 if (!isSupported) {\r
10550 if (element.setAttribute && element.removeAttribute) {\r
10551 element.setAttribute(eventName, '');\r
10552 isSupported = typeof element[eventName] === 'function';\r
10553 if (typeof element[eventName] !== 'undefined') {\r
10554 element[eventName] = undefined;\r
10555 }\r
10556 element.removeAttribute(eventName);\r
10557 }\r
10558 }\r
10559 return isSupported;\r
10560 },\r
10561 // Browser Detection\r
10562 getBrowsers = function() {\r
10563 var browsers = {},\r
10564 maxIEVersion, prefix, value, key, index, len, match, version, matched;\r
10565 // MS Edge browser (and possibly others) can report multiple browsers in the UserAgent\r
10566 // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"\r
10567 // we use this to prioritize the actual browser in this situation\r
10568 len = me.browserPriority.length;\r
10569 for (index = 0; index < len; index++) {\r
10570 key = me.browserPriority[index];\r
10571 if (!matched) {\r
10572 value = me.browserPrefixes[key];\r
10573 match = ua.match(new RegExp('(' + value + ')([\\w\\._]+)'));\r
10574 version = match && match.length > 1 ? parseInt(match[2]) : 0;\r
10575 if (version) {\r
10576 matched = true;\r
10577 }\r
10578 } else {\r
10579 version = 0;\r
10580 }\r
10581 browsers[key] = version;\r
10582 }\r
10583 //Deal with IE document mode\r
10584 if (browsers.ie) {\r
10585 var mode = document.documentMode;\r
10586 if (mode >= 8) {\r
10587 browsers.ie = mode;\r
10588 }\r
10589 }\r
10590 // Fancy IE greater than and less then quick tags\r
10591 version = browsers.ie || false;\r
10592 maxIEVersion = Math.max(version, me.maxIEVersion);\r
10593 for (index = 8; index <= maxIEVersion; ++index) {\r
10594 prefix = 'ie' + index;\r
10595 browsers[prefix + 'm'] = version ? version <= index : 0;\r
10596 browsers[prefix] = version ? version === index : 0;\r
10597 browsers[prefix + 'p'] = version ? version >= index : 0;\r
10598 }\r
10599 return browsers;\r
10600 },\r
10601 //OS Detection\r
10602 getOperatingSystems = function() {\r
10603 var systems = {},\r
10604 value, key, keys, index, len, match, matched, version, activeCount;\r
10605 keys = _getKeys(me.osPrefixes);\r
10606 len = keys.length;\r
10607 for (index = 0 , activeCount = 0; index < len; index++) {\r
10608 key = keys[index];\r
10609 value = me.osPrefixes[key];\r
10610 match = ua.match(new RegExp('(' + value + ')([^\\s;]+)'));\r
10611 matched = match ? match[1] : null;\r
10612 // This is here because some HTC android devices show an OSX Snow Leopard userAgent by default.\r
10613 // And the Kindle Fire doesn't have any indicator of Android as the OS in its User Agent\r
10614 if (matched && (matched === 'HTC_' || matched === 'Silk/')) {\r
10615 version = 2.3;\r
10616 } else {\r
10617 version = match && match.length > 1 ? parseFloat(match[match.length - 1]) : 0;\r
10618 }\r
10619 if (version) {\r
10620 activeCount++;\r
10621 }\r
10622 systems[key] = version;\r
10623 }\r
10624 keys = _getKeys(me.fallbackOSPrefixes);\r
10625 // If no OS could be found we resort to the fallbacks, otherwise we just\r
10626 // falsify the fallbacks\r
10627 len = keys.length;\r
10628 for (index = 0; index < len; index++) {\r
10629 key = keys[index];\r
10630 // No OS was detected from osPrefixes\r
10631 if (activeCount === 0) {\r
10632 value = me.fallbackOSPrefixes[key];\r
10633 match = ua.toLowerCase().match(new RegExp(value));\r
10634 systems[key] = match ? true : 0;\r
10635 } else {\r
10636 systems[key] = 0;\r
10637 }\r
10638 }\r
10639 return systems;\r
10640 },\r
10641 // Device Detection\r
10642 getDevices = function() {\r
10643 var devices = {},\r
10644 value, key, keys, index, len, match;\r
10645 keys = _getKeys(me.devicePrefixes);\r
10646 len = keys.length;\r
10647 for (index = 0; index < len; index++) {\r
10648 key = keys[index];\r
10649 value = me.devicePrefixes[key];\r
10650 match = ua.match(new RegExp(value));\r
10651 devices[key] = match ? true : 0;\r
10652 }\r
10653 return devices;\r
10654 },\r
10655 browsers = getBrowsers(),\r
10656 systems = getOperatingSystems(),\r
10657 devices = getDevices(),\r
10658 platformParams = Boot.loadPlatformsParam();\r
10659 // We apply platformParams from the query here first to allow for forced user valued\r
10660 // to be used in calculation of generated tags\r
10661 _merge(_tags, browsers, systems, devices, platformParams, true);\r
10662 _tags.phone = (_tags.iphone || _tags.ipod) || (!_tags.silk && (_tags.android && (_tags.android < 3 || isMobile))) || (_tags.blackberry && isMobile) || (_tags.windowsphone);\r
10663 _tags.tablet = !_tags.phone && (_tags.ipad || _tags.android || _tags.silk || _tags.rimtablet || (_tags.ie10 && /; Touch/.test(ua)));\r
10664 _tags.touch = // if the browser has touch events we can be reasonably sure the device has\r
10665 // a touch screen\r
10666 isEventSupported('touchend') || // browsers that use pointer event have maxTouchPoints > 0 if the\r
10667 // device supports touch input\r
10668 // http://www.w3.org/TR/pointerevents/#widl-Navigator-maxTouchPoints\r
10669 navigator.maxTouchPoints || // IE10 uses a vendor-prefixed maxTouchPoints property\r
10670 navigator.msMaxTouchPoints;\r
10671 _tags.desktop = !_tags.phone && !_tags.tablet;\r
10672 _tags.cordova = _tags.phonegap = !!(window.PhoneGap || window.Cordova || window.cordova);\r
10673 _tags.webview = /(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)(?!.*FBAN)/i.test(ua);\r
10674 _tags.androidstock = (_tags.android <= 4.3) && (_tags.safari || _tags.silk);\r
10675 // Re-apply any query params here to allow for user override of generated tags (desktop, touch, tablet, etc)\r
10676 _merge(_tags, platformParams, true);\r
10677 },\r
10678 /**
10679 * Extracts user supplied platform tags from the "platformTags" query parameter
10680 * of the form:
10681 *
10682 * ?platformTags=name:state,name:state,...
10683 *
10684 * (each tag defaults to true when state is unspecified)
10685 *
10686 * Example:
10687 * ?platformTags=isTablet,isPhone:false,isDesktop:0,iOS:1,Safari:true, ...
10688 *
10689 * @returns {Object} the platform tags supplied by the query string
10690 */\r
10691 loadPlatformsParam: function() {\r
10692 // Check if the ?platform parameter is set in the URL\r
10693 var paramsString = window.location.search.substr(1),\r
10694 paramsArray = paramsString.split("&"),\r
10695 params = {},\r
10696 i,\r
10697 platforms = {},\r
10698 tmpArray, tmplen, platform, name, enabled;\r
10699 for (i = 0; i < paramsArray.length; i++) {\r
10700 tmpArray = paramsArray[i].split("=");\r
10701 params[tmpArray[0]] = tmpArray[1];\r
10702 }\r
10703 if (params.platformTags) {\r
10704 tmpArray = params.platformTags.split(",");\r
10705 for (tmplen = tmpArray.length , i = 0; i < tmplen; i++) {\r
10706 platform = tmpArray[i].split(":");\r
10707 name = platform[0];\r
10708 enabled = true;\r
10709 if (platform.length > 1) {\r
10710 enabled = platform[1];\r
10711 if (enabled === 'false' || enabled === '0') {\r
10712 enabled = false;\r
10713 }\r
10714 }\r
10715 platforms[name] = enabled;\r
10716 }\r
10717 }\r
10718 return platforms;\r
10719 },\r
10720 filterPlatform: function(platform, excludes) {\r
10721 platform = _emptyArray.concat(platform || _emptyArray);\r
10722 excludes = _emptyArray.concat(excludes || _emptyArray);\r
10723 var plen = platform.length,\r
10724 elen = excludes.length,\r
10725 include = (!plen && elen),\r
10726 // default true if only excludes specified\r
10727 i, tag;\r
10728 for (i = 0; i < plen && !include; i++) {\r
10729 tag = platform[i];\r
10730 include = !!_tags[tag];\r
10731 }\r
10732 for (i = 0; i < elen && include; i++) {\r
10733 tag = excludes[i];\r
10734 include = !_tags[tag];\r
10735 }\r
10736 return include;\r
10737 },\r
10738 init: function() {\r
10739 var scriptEls = doc.getElementsByTagName('script'),\r
10740 len = scriptEls.length,\r
10741 re = /\/ext(\-[a-z\-]+)?\.js$/,\r
10742 entry, script, src, state, baseUrl, key, n, origin;\r
10743 // Since we are loading after other scripts, and we needed to gather them\r
10744 // anyway, we track them in _scripts so we don't have to ask for them all\r
10745 // repeatedly.\r
10746 for (n = 0; n < len; n++) {\r
10747 src = (script = scriptEls[n]).src;\r
10748 if (!src) {\r
10749 \r
10750 continue;\r
10751 }\r
10752 state = script.readyState || null;\r
10753 // If we find a script file called "ext-*.js", then the base path is that file's base path.\r
10754 if (!baseUrl) {\r
10755 if (re.test(src)) {\r
10756 Boot.hasReadyState = ("readyState" in script);\r
10757 Boot.hasAsync = ("async" in script) || !Boot.hasReadyState;\r
10758 baseUrl = src;\r
10759 }\r
10760 }\r
10761 if (!Boot.scripts[key = Boot.canonicalUrl(src)]) {\r
10762 _debug("creating entry " + key + " in Boot.init");\r
10763 entry = new Entry({\r
10764 key: key,\r
10765 url: src,\r
10766 done: state === null || // non-IE\r
10767 state === 'loaded' || state === 'complete',\r
10768 // IE only\r
10769 el: script,\r
10770 prop: 'src'\r
10771 });\r
10772 }\r
10773 }\r
10774 if (!baseUrl) {\r
10775 script = scriptEls[scriptEls.length - 1];\r
10776 baseUrl = script.src;\r
10777 Boot.hasReadyState = ('readyState' in script);\r
10778 Boot.hasAsync = ("async" in script) || !Boot.hasReadyState;\r
10779 }\r
10780 Boot.baseUrl = baseUrl.substring(0, baseUrl.lastIndexOf('/') + 1);\r
10781 origin = window.location.origin || window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '');\r
10782 Boot.origin = origin;\r
10783 Boot.detectPlatformTags();\r
10784 Ext.filterPlatform = Boot.filterPlatform;\r
10785 },\r
10786 /*
10787 * This method returns a canonical URL for the given URL.
10788 *
10789 * For example, the following all produce the same canonical URL (which is the
10790 * last one):
10791 *
10792 * http://foo.com/bar/baz/zoo/derp/../../goo/Thing.js?_dc=12345
10793 * http://foo.com/bar/baz/zoo/derp/../../goo/Thing.js
10794 * http://foo.com/bar/baz/zoo/derp/../jazz/../../goo/Thing.js
10795 * http://foo.com/bar/baz/zoo/../goo/Thing.js
10796 * http://foo.com/bar/baz/goo/Thing.js
10797 *
10798 * @private
10799 */\r
10800 canonicalUrl: function(url) {\r
10801 // @TODO - see if we need this fallback logic\r
10802 // http://stackoverflow.com/questions/470832/getting-an-absolute-url-from-a-relative-one-ie6-issue\r
10803 resolverEl.href = url;\r
10804 var ret = resolverEl.href,\r
10805 dc = _config.disableCachingParam,\r
10806 pos = dc ? ret.indexOf(dc + '=') : -1,\r
10807 c, end;\r
10808 // If we have a _dc query parameter we need to remove it from the canonical\r
10809 // URL.\r
10810 if (pos > 0 && ((c = ret.charAt(pos - 1)) === '?' || c === '&')) {\r
10811 end = ret.indexOf('&', pos);\r
10812 end = (end < 0) ? '' : ret.substring(end);\r
10813 if (end && c === '?') {\r
10814 ++pos;\r
10815 // keep the '?'\r
10816 end = end.substring(1);\r
10817 }\r
10818 // remove the '&'\r
10819 ret = ret.substring(0, pos - 1) + end;\r
10820 }\r
10821 return ret;\r
10822 },\r
10823 /*
10824 * Get the config value corresponding to the specified name. If no name is given, will return the config object
10825 * @param {String} name The config property name
10826 * @return {Object}
10827 */\r
10828 getConfig: function(name) {\r
10829 return name ? Boot.config[name] : Boot.config;\r
10830 },\r
10831 /*
10832 * Set the configuration.
10833 * @param {Object} config The config object to override the default values.
10834 * @return {Ext.Boot} this
10835 */\r
10836 setConfig: function(name, value) {\r
10837 if (typeof name === 'string') {\r
10838 Boot.config[name] = value;\r
10839 } else {\r
10840 for (var s in name) {\r
10841 Boot.setConfig(s, name[s]);\r
10842 }\r
10843 }\r
10844 return Boot;\r
10845 },\r
10846 getHead: function() {\r
10847 return Boot.docHead || (Boot.docHead = doc.head || doc.getElementsByTagName('head')[0]);\r
10848 },\r
10849 create: function(url, key, cfg) {\r
10850 var config = cfg || {};\r
10851 config.url = url;\r
10852 config.key = key;\r
10853 return Boot.scripts[key] = new Entry(config);\r
10854 },\r
10855 getEntry: function(url, cfg) {\r
10856 var key = Boot.canonicalUrl(url),\r
10857 entry = Boot.scripts[key];\r
10858 if (!entry) {\r
10859 entry = Boot.create(url, key, cfg);\r
10860 }\r
10861 return entry;\r
10862 },\r
10863 registerContent: function(url, type, content) {\r
10864 var cfg = {\r
10865 content: content,\r
10866 loaded: true,\r
10867 css: type === 'css'\r
10868 };\r
10869 return Boot.getEntry(url, cfg);\r
10870 },\r
10871 processRequest: function(request, sync) {\r
10872 request.loadEntries(sync);\r
10873 },\r
10874 load: function(request) {\r
10875 _debug("Boot.load called");\r
10876 var request = new Request(request);\r
10877 if (request.sync || Boot.syncMode) {\r
10878 return Boot.loadSync(request);\r
10879 }\r
10880 // If there is a request in progress, we must\r
10881 // queue this new request to be fired when the current request completes.\r
10882 if (Boot.currentRequest) {\r
10883 _debug("current active request, suspending this request");\r
10884 // trigger assignment of entries now to ensure that overlapping\r
10885 // entries with currently running requests will synchronize state\r
10886 // with this pending one as they complete\r
10887 request.getEntries();\r
10888 Boot.suspendedQueue.push(request);\r
10889 } else {\r
10890 Boot.currentRequest = request;\r
10891 Boot.processRequest(request, false);\r
10892 }\r
10893 return Boot;\r
10894 },\r
10895 loadSync: function(request) {\r
10896 _debug("Boot.loadSync called");\r
10897 var request = new Request(request);\r
10898 Boot.syncMode++;\r
10899 Boot.processRequest(request, true);\r
10900 Boot.syncMode--;\r
10901 return Boot;\r
10902 },\r
10903 loadBasePrefix: function(request) {\r
10904 request = new Request(request);\r
10905 request.prependBaseUrl = true;\r
10906 return Boot.load(request);\r
10907 },\r
10908 loadSyncBasePrefix: function(request) {\r
10909 request = new Request(request);\r
10910 request.prependBaseUrl = true;\r
10911 return Boot.loadSync(request);\r
10912 },\r
10913 requestComplete: function(request) {\r
10914 var next;\r
10915 if (Boot.currentRequest === request) {\r
10916 Boot.currentRequest = null;\r
10917 while (Boot.suspendedQueue.length > 0) {\r
10918 next = Boot.suspendedQueue.shift();\r
10919 if (!next.done) {\r
10920 _debug("resuming suspended request");\r
10921 Boot.load(next);\r
10922 break;\r
10923 }\r
10924 }\r
10925 }\r
10926 if (!Boot.currentRequest && Boot.suspendedQueue.length == 0) {\r
10927 Boot.fireListeners();\r
10928 }\r
10929 },\r
10930 isLoading: function() {\r
10931 return !Boot.currentRequest && Boot.suspendedQueue.length == 0;\r
10932 },\r
10933 fireListeners: function() {\r
10934 var listener;\r
10935 while (Boot.isLoading() && (listener = Boot.listeners.shift())) {\r
10936 listener();\r
10937 }\r
10938 },\r
10939 onBootReady: function(listener) {\r
10940 if (!Boot.isLoading()) {\r
10941 listener();\r
10942 } else {\r
10943 Boot.listeners.push(listener);\r
10944 }\r
10945 },\r
10946 /*
10947 * this is a helper function used by Ext.Loader to flush out
10948 * 'uses' arrays for classes
10949 */\r
10950 getPathsFromIndexes: function(indexMap, loadOrder) {\r
10951 return Request.prototype.getPathsFromIndexes(indexMap, loadOrder);\r
10952 },\r
10953 createLoadOrderMap: function(loadOrder) {\r
10954 return Request.prototype.createLoadOrderMap(loadOrder);\r
10955 },\r
10956 fetch: function(url, complete, scope, async) {\r
10957 async = (async === undefined) ? !!complete : async;\r
10958 var xhr = new XMLHttpRequest(),\r
10959 result, status, content,\r
10960 exception = false,\r
10961 readyStateChange = function() {\r
10962 if (xhr && xhr.readyState == 4) {\r
10963 status = (xhr.status === 1223) ? 204 : (xhr.status === 0 && ((self.location || {}).protocol === 'file:' || (self.location || {}).protocol === 'ionp:')) ? 200 : xhr.status;\r
10964 content = xhr.responseText;\r
10965 result = {\r
10966 content: content,\r
10967 status: status,\r
10968 exception: exception\r
10969 };\r
10970 if (complete) {\r
10971 complete.call(scope, result);\r
10972 }\r
10973 xhr = null;\r
10974 }\r
10975 };\r
10976 if (async) {\r
10977 xhr.onreadystatechange = readyStateChange;\r
10978 }\r
10979 try {\r
10980 _debug("fetching " + url + " " + (async ? "async" : "sync"));\r
10981 xhr.open('GET', url, async);\r
10982 xhr.send(null);\r
10983 } catch (err) {\r
10984 exception = err;\r
10985 readyStateChange();\r
10986 return result;\r
10987 }\r
10988 if (!async) {\r
10989 readyStateChange();\r
10990 }\r
10991 return result;\r
10992 },\r
10993 notifyAll: function(entry) {\r
10994 entry.notifyRequests();\r
10995 }\r
10996 };\r
10997 /*
10998 * The request class encapsulates a series of Entry objects
10999 * and provides notification around the completion of all Entries
11000 * in this request.
11001 */\r
11002 function Request(cfg) {\r
11003 if (cfg.$isRequest) {\r
11004 return cfg;\r
11005 }\r
11006 var cfg = cfg.url ? cfg : {\r
11007 url: cfg\r
11008 },\r
11009 url = cfg.url,\r
11010 urls = url.charAt ? [\r
11011 url\r
11012 ] : url,\r
11013 charset = cfg.charset || Boot.config.charset;\r
11014 _apply(cfg, {\r
11015 urls: urls,\r
11016 charset: charset\r
11017 });\r
11018 _apply(this, cfg);\r
11019 }\r
11020 \r
11021 Request.prototype = {\r
11022 $isRequest: true,\r
11023 /*
11024 * @private
11025 * @param manifest
11026 * @returns {*}
11027 */\r
11028 createLoadOrderMap: function(loadOrder) {\r
11029 var len = loadOrder.length,\r
11030 loadOrderMap = {},\r
11031 i, element;\r
11032 for (i = 0; i < len; i++) {\r
11033 element = loadOrder[i];\r
11034 loadOrderMap[element.path] = element;\r
11035 }\r
11036 return loadOrderMap;\r
11037 },\r
11038 /*
11039 * @private
11040 * @param index
11041 * @param indexMap
11042 * @returns {{}}
11043 */\r
11044 getLoadIndexes: function(index, indexMap, loadOrder, includeUses, skipLoaded) {\r
11045 var item = loadOrder[index],\r
11046 len, i, reqs, entry, stop, added, idx, ridx, url;\r
11047 if (indexMap[index]) {\r
11048 // prevent cycles\r
11049 return indexMap;\r
11050 }\r
11051 indexMap[index] = true;\r
11052 stop = false;\r
11053 while (!stop) {\r
11054 added = false;\r
11055 // iterate the requirements for each index and\r
11056 // accumulate in the index map\r
11057 for (idx in indexMap) {\r
11058 if (indexMap.hasOwnProperty(idx)) {\r
11059 item = loadOrder[idx];\r
11060 if (!item) {\r
11061 \r
11062 continue;\r
11063 }\r
11064 url = this.prepareUrl(item.path);\r
11065 entry = Boot.getEntry(url);\r
11066 if (!skipLoaded || !entry || !entry.done) {\r
11067 reqs = item.requires;\r
11068 if (includeUses && item.uses) {\r
11069 reqs = reqs.concat(item.uses);\r
11070 }\r
11071 for (len = reqs.length , i = 0; i < len; i++) {\r
11072 ridx = reqs[i];\r
11073 // if we find a requirement that wasn't\r
11074 // already in the index map,\r
11075 // set the added flag to indicate we need to\r
11076 // reprocess\r
11077 if (!indexMap[ridx]) {\r
11078 indexMap[ridx] = true;\r
11079 added = true;\r
11080 }\r
11081 }\r
11082 }\r
11083 }\r
11084 }\r
11085 // if we made a pass through the index map and didn't add anything\r
11086 // then we can stop\r
11087 if (!added) {\r
11088 stop = true;\r
11089 }\r
11090 }\r
11091 return indexMap;\r
11092 },\r
11093 getPathsFromIndexes: function(indexMap, loadOrder) {\r
11094 var indexes = [],\r
11095 paths = [],\r
11096 index, len, i;\r
11097 for (index in indexMap) {\r
11098 if (indexMap.hasOwnProperty(index) && indexMap[index]) {\r
11099 indexes.push(index);\r
11100 }\r
11101 }\r
11102 indexes.sort(function(a, b) {\r
11103 return a - b;\r
11104 });\r
11105 // convert indexes back into load paths\r
11106 for (len = indexes.length , i = 0; i < len; i++) {\r
11107 paths.push(loadOrder[indexes[i]].path);\r
11108 }\r
11109 return paths;\r
11110 },\r
11111 expandUrl: function(url, indexMap, includeUses, skipLoaded) {\r
11112 if (typeof url == 'string') {\r
11113 url = [\r
11114 url\r
11115 ];\r
11116 }\r
11117 var me = this,\r
11118 loadOrder = me.loadOrder,\r
11119 loadOrderMap = me.loadOrderMap;\r
11120 if (loadOrder) {\r
11121 loadOrderMap = loadOrderMap || me.createLoadOrderMap(loadOrder);\r
11122 me.loadOrderMap = loadOrderMap;\r
11123 indexMap = indexMap || {};\r
11124 var len = url.length,\r
11125 unmapped = [],\r
11126 i, item;\r
11127 for (i = 0; i < len; i++) {\r
11128 item = loadOrderMap[url[i]];\r
11129 if (item) {\r
11130 me.getLoadIndexes(item.idx, indexMap, loadOrder, includeUses, skipLoaded);\r
11131 } else {\r
11132 unmapped.push(url[i]);\r
11133 }\r
11134 }\r
11135 return me.getPathsFromIndexes(indexMap, loadOrder).concat(unmapped);\r
11136 }\r
11137 return url;\r
11138 },\r
11139 expandUrls: function(urls, includeUses) {\r
11140 if (typeof urls == "string") {\r
11141 urls = [\r
11142 urls\r
11143 ];\r
11144 }\r
11145 var expanded = [],\r
11146 expandMap = {},\r
11147 tmpExpanded,\r
11148 len = urls.length,\r
11149 i, t, tlen, tUrl;\r
11150 for (i = 0; i < len; i++) {\r
11151 tmpExpanded = this.expandUrl(urls[i], {}, includeUses, true);\r
11152 for (t = 0 , tlen = tmpExpanded.length; t < tlen; t++) {\r
11153 tUrl = tmpExpanded[t];\r
11154 if (!expandMap[tUrl]) {\r
11155 expandMap[tUrl] = true;\r
11156 expanded.push(tUrl);\r
11157 }\r
11158 }\r
11159 }\r
11160 if (expanded.length == 0) {\r
11161 expanded = urls;\r
11162 }\r
11163 return expanded;\r
11164 },\r
11165 expandLoadOrder: function() {\r
11166 var me = this,\r
11167 urls = me.urls,\r
11168 expanded;\r
11169 if (!me.expanded) {\r
11170 expanded = this.expandUrls(urls, true);\r
11171 me.expanded = true;\r
11172 } else {\r
11173 expanded = urls;\r
11174 }\r
11175 me.urls = expanded;\r
11176 // if we added some urls to the request to honor the indicated\r
11177 // load order, the request needs to be sequential\r
11178 if (urls.length != expanded.length) {\r
11179 me.sequential = true;\r
11180 }\r
11181 return me;\r
11182 },\r
11183 getUrls: function() {\r
11184 this.expandLoadOrder();\r
11185 return this.urls;\r
11186 },\r
11187 prepareUrl: function(url) {\r
11188 if (this.prependBaseUrl) {\r
11189 return Boot.baseUrl + url;\r
11190 }\r
11191 return url;\r
11192 },\r
11193 getEntries: function() {\r
11194 var me = this,\r
11195 entries = me.entries,\r
11196 i, entry, urls, url;\r
11197 if (!entries) {\r
11198 entries = [];\r
11199 urls = me.getUrls();\r
11200 for (i = 0; i < urls.length; i++) {\r
11201 url = me.prepareUrl(urls[i]);\r
11202 entry = Boot.getEntry(url, {\r
11203 buster: me.buster,\r
11204 charset: me.charset\r
11205 });\r
11206 entry.requests.push(me);\r
11207 entries.push(entry);\r
11208 }\r
11209 me.entries = entries;\r
11210 }\r
11211 return entries;\r
11212 },\r
11213 loadEntries: function(sync) {\r
11214 var me = this,\r
11215 entries = me.getEntries(),\r
11216 len = entries.length,\r
11217 start = me.loadStart || 0,\r
11218 continueLoad, entry, i;\r
11219 if (sync !== undefined) {\r
11220 me.sync = sync;\r
11221 }\r
11222 me.loaded = me.loaded || 0;\r
11223 me.loading = me.loading || len;\r
11224 for (i = start; i < len; i++) {\r
11225 entry = entries[i];\r
11226 if (!entry.loaded) {\r
11227 continueLoad = entries[i].load(me.sync);\r
11228 } else {\r
11229 continueLoad = true;\r
11230 }\r
11231 if (!continueLoad) {\r
11232 me.loadStart = i;\r
11233 entry.onDone(function() {\r
11234 me.loadEntries(sync);\r
11235 });\r
11236 break;\r
11237 }\r
11238 }\r
11239 me.processLoadedEntries();\r
11240 },\r
11241 processLoadedEntries: function() {\r
11242 var me = this,\r
11243 entries = me.getEntries(),\r
11244 len = entries.length,\r
11245 start = me.startIndex || 0,\r
11246 i, entry;\r
11247 if (!me.done) {\r
11248 for (i = start; i < len; i++) {\r
11249 entry = entries[i];\r
11250 if (!entry.loaded) {\r
11251 me.startIndex = i;\r
11252 return;\r
11253 }\r
11254 if (!entry.evaluated) {\r
11255 entry.evaluate();\r
11256 }\r
11257 if (entry.error) {\r
11258 me.error = true;\r
11259 }\r
11260 }\r
11261 me.notify();\r
11262 }\r
11263 },\r
11264 notify: function() {\r
11265 var me = this;\r
11266 if (!me.done) {\r
11267 var error = me.error,\r
11268 fn = me[error ? 'failure' : 'success'],\r
11269 delay = ('delay' in me) ? me.delay : (error ? 1 : Boot.config.chainDelay),\r
11270 scope = me.scope || me;\r
11271 me.done = true;\r
11272 if (fn) {\r
11273 if (delay === 0 || delay > 0) {\r
11274 // Free the stack (and defer the next script)\r
11275 setTimeout(function() {\r
11276 fn.call(scope, me);\r
11277 }, delay);\r
11278 } else {\r
11279 fn.call(scope, me);\r
11280 }\r
11281 }\r
11282 me.fireListeners();\r
11283 Boot.requestComplete(me);\r
11284 }\r
11285 },\r
11286 onDone: function(listener) {\r
11287 var me = this,\r
11288 listeners = me.listeners || (me.listeners = []);\r
11289 if (me.done) {\r
11290 listener(me);\r
11291 } else {\r
11292 listeners.push(listener);\r
11293 }\r
11294 },\r
11295 fireListeners: function() {\r
11296 var listeners = this.listeners,\r
11297 listener;\r
11298 if (listeners) {\r
11299 _debug("firing request listeners");\r
11300 while ((listener = listeners.shift())) {\r
11301 listener(this);\r
11302 }\r
11303 }\r
11304 }\r
11305 };\r
11306 /*
11307 * The Entry class is a token to manage the load and evaluation
11308 * state of a particular url. It is used to notify all Requests
11309 * interested in this url that the content is available.
11310 */\r
11311 function Entry(cfg) {\r
11312 if (cfg.$isEntry) {\r
11313 return cfg;\r
11314 }\r
11315 _debug("creating entry for " + cfg.url);\r
11316 var charset = cfg.charset || Boot.config.charset,\r
11317 manifest = Ext.manifest,\r
11318 loader = manifest && manifest.loader,\r
11319 cache = (cfg.cache !== undefined) ? cfg.cache : (loader && loader.cache),\r
11320 buster, busterParam;\r
11321 if (Boot.config.disableCaching) {\r
11322 if (cache === undefined) {\r
11323 cache = !Boot.config.disableCaching;\r
11324 }\r
11325 if (cache === false) {\r
11326 buster = +new Date();\r
11327 } else if (cache !== true) {\r
11328 buster = cache;\r
11329 }\r
11330 if (buster) {\r
11331 busterParam = (loader && loader.cacheParam) || Boot.config.disableCachingParam;\r
11332 buster = busterParam + "=" + buster;\r
11333 }\r
11334 }\r
11335 _apply(cfg, {\r
11336 charset: charset,\r
11337 buster: buster,\r
11338 requests: []\r
11339 });\r
11340 _apply(this, cfg);\r
11341 }\r
11342 \r
11343 Entry.prototype = {\r
11344 $isEntry: true,\r
11345 done: false,\r
11346 evaluated: false,\r
11347 loaded: false,\r
11348 isCrossDomain: function() {\r
11349 var me = this;\r
11350 if (me.crossDomain === undefined) {\r
11351 _debug("checking " + me.getLoadUrl() + " for prefix " + Boot.origin);\r
11352 me.crossDomain = (me.getLoadUrl().indexOf(Boot.origin) !== 0);\r
11353 }\r
11354 return me.crossDomain;\r
11355 },\r
11356 isCss: function() {\r
11357 var me = this;\r
11358 if (me.css === undefined) {\r
11359 if (me.url) {\r
11360 var assetConfig = Boot.assetConfig[me.url];\r
11361 me.css = assetConfig ? assetConfig.type === "css" : cssRe.test(me.url);\r
11362 } else {\r
11363 me.css = false;\r
11364 }\r
11365 }\r
11366 return this.css;\r
11367 },\r
11368 getElement: function(tag) {\r
11369 var me = this,\r
11370 el = me.el;\r
11371 if (!el) {\r
11372 _debug("creating element for " + me.url);\r
11373 if (me.isCss()) {\r
11374 tag = tag || "link";\r
11375 el = doc.createElement(tag);\r
11376 if (tag == "link") {\r
11377 el.rel = 'stylesheet';\r
11378 me.prop = 'href';\r
11379 } else {\r
11380 me.prop = "textContent";\r
11381 }\r
11382 el.type = "text/css";\r
11383 } else {\r
11384 tag = tag || "script";\r
11385 el = doc.createElement(tag);\r
11386 el.type = 'text/javascript';\r
11387 me.prop = 'src';\r
11388 if (me.charset) {\r
11389 el.charset = me.charset;\r
11390 }\r
11391 if (Boot.hasAsync) {\r
11392 el.async = false;\r
11393 }\r
11394 }\r
11395 me.el = el;\r
11396 }\r
11397 return el;\r
11398 },\r
11399 getLoadUrl: function() {\r
11400 var me = this,\r
11401 url = Boot.canonicalUrl(me.url);\r
11402 if (!me.loadUrl) {\r
11403 me.loadUrl = !!me.buster ? (url + (url.indexOf('?') === -1 ? '?' : '&') + me.buster) : url;\r
11404 }\r
11405 return me.loadUrl;\r
11406 },\r
11407 fetch: function(req) {\r
11408 var url = this.getLoadUrl(),\r
11409 async = !!req.async,\r
11410 complete = req.complete;\r
11411 Boot.fetch(url, complete, this, async);\r
11412 },\r
11413 onContentLoaded: function(response) {\r
11414 var me = this,\r
11415 status = response.status,\r
11416 content = response.content,\r
11417 exception = response.exception,\r
11418 url = this.getLoadUrl();\r
11419 me.loaded = true;\r
11420 if ((exception || status === 0) && !_environment.phantom) {\r
11421 me.error = ("Failed loading synchronously via XHR: '" + url + "'. It's likely that the file is either being loaded from a " + "different domain or from the local file system where cross " + "origin requests are not allowed for security reasons. Try " + "asynchronous loading instead.") || true;\r
11422 me.evaluated = true;\r
11423 } else if ((status >= 200 && status < 300) || status === 304 || _environment.phantom || (status === 0 && content.length > 0)) {\r
11424 me.content = content;\r
11425 } else {\r
11426 me.error = ("Failed loading synchronously via XHR: '" + url + "'. Please verify that the file exists. XHR status code: " + status) || true;\r
11427 me.evaluated = true;\r
11428 }\r
11429 },\r
11430 createLoadElement: function(callback) {\r
11431 var me = this,\r
11432 el = me.getElement(),\r
11433 readyStateChange = function() {\r
11434 if (this.readyState === 'loaded' || this.readyState === 'complete') {\r
11435 if (callback) {\r
11436 callback();\r
11437 }\r
11438 }\r
11439 },\r
11440 errorFn = function() {\r
11441 me.error = true;\r
11442 if (callback) {\r
11443 callback();\r
11444 }\r
11445 };\r
11446 me.preserve = true;\r
11447 el.onerror = errorFn;\r
11448 if (Boot.hasReadyState) {\r
11449 el.onreadystatechange = readyStateChange;\r
11450 } else {\r
11451 el.onload = callback;\r
11452 }\r
11453 // IE starts loading here\r
11454 el[me.prop] = me.getLoadUrl();\r
11455 },\r
11456 onLoadElementReady: function() {\r
11457 Boot.getHead().appendChild(this.getElement());\r
11458 this.evaluated = true;\r
11459 },\r
11460 inject: function(content, asset) {\r
11461 _debug("injecting content for " + this.url);\r
11462 var me = this,\r
11463 head = Boot.getHead(),\r
11464 url = me.url,\r
11465 key = me.key,\r
11466 base, el, ieMode, basePath;\r
11467 if (me.isCss()) {\r
11468 me.preserve = true;\r
11469 basePath = key.substring(0, key.lastIndexOf("/") + 1);\r
11470 base = doc.createElement('base');\r
11471 base.href = basePath;\r
11472 if (head.firstChild) {\r
11473 head.insertBefore(base, head.firstChild);\r
11474 } else {\r
11475 head.appendChild(base);\r
11476 }\r
11477 // reset the href attribute to cuase IE to pick up the change\r
11478 base.href = base.href;\r
11479 if (url) {\r
11480 content += "\n/*# sourceURL=" + key + " */";\r
11481 }\r
11482 // create element after setting base\r
11483 el = me.getElement("style");\r
11484 ieMode = ('styleSheet' in el);\r
11485 head.appendChild(base);\r
11486 if (ieMode) {\r
11487 head.appendChild(el);\r
11488 el.styleSheet.cssText = content;\r
11489 } else {\r
11490 el.textContent = content;\r
11491 head.appendChild(el);\r
11492 }\r
11493 head.removeChild(base);\r
11494 } else {\r
11495 // Debugger friendly, file names are still shown even though they're\r
11496 // eval'ed code. Breakpoints work on both Firebug and Chrome's Web\r
11497 // Inspector.\r
11498 if (url) {\r
11499 content += "\n//# sourceURL=" + key;\r
11500 }\r
11501 Ext.globalEval(content);\r
11502 }\r
11503 return me;\r
11504 },\r
11505 loadCrossDomain: function() {\r
11506 var me = this,\r
11507 complete = function() {\r
11508 me.loaded = me.evaluated = me.done = true;\r
11509 me.notifyRequests();\r
11510 };\r
11511 me.createLoadElement(function() {\r
11512 complete();\r
11513 });\r
11514 me.evaluateLoadElement();\r
11515 // at this point, we need sequential evaluation,\r
11516 // which means we can't advance the load until\r
11517 // this entry has fully completed\r
11518 return false;\r
11519 },\r
11520 loadElement: function() {\r
11521 var me = this,\r
11522 complete = function() {\r
11523 me.loaded = me.evaluated = me.done = true;\r
11524 me.notifyRequests();\r
11525 };\r
11526 me.createLoadElement(function() {\r
11527 complete();\r
11528 });\r
11529 me.evaluateLoadElement();\r
11530 return true;\r
11531 },\r
11532 loadSync: function() {\r
11533 var me = this;\r
11534 me.fetch({\r
11535 async: false,\r
11536 complete: function(response) {\r
11537 me.onContentLoaded(response);\r
11538 }\r
11539 });\r
11540 me.evaluate();\r
11541 me.notifyRequests();\r
11542 },\r
11543 load: function(sync) {\r
11544 var me = this;\r
11545 if (!me.loaded) {\r
11546 if (me.loading) {\r
11547 // if we're calling back through load and we're loading but haven't\r
11548 // yet loaded, then we should be in a sequential, cross domain\r
11549 // load scenario which means we can't continue the load on the\r
11550 // request until this entry has fully evaluated, which will mean\r
11551 // loaded = evaluated = done = true in one step. For css files, this\r
11552 // will happen immediately upon <link> element creation / insertion,\r
11553 // but <script> elements will set this upon load notification\r
11554 return false;\r
11555 }\r
11556 me.loading = true;\r
11557 // for async modes, we have some options\r
11558 if (!sync) {\r
11559 // if cross domain, just inject the script tag and let the onload\r
11560 // events drive the progression\r
11561 if (me.isCrossDomain()) {\r
11562 return me.loadCrossDomain();\r
11563 }\r
11564 // for IE, use the readyStateChange allows us to load scripts in parallel\r
11565 // but serialize the evaluation by appending the script node to the\r
11566 // document\r
11567 else if (!me.isCss() && Boot.hasReadyState) {\r
11568 me.createLoadElement(function() {\r
11569 me.loaded = true;\r
11570 me.notifyRequests();\r
11571 });\r
11572 } else if (Boot.useElements && // older webkit, phantomjs included, won't fire load for link elements\r
11573 !(me.isCss() && _environment.phantom)) {\r
11574 return me.loadElement();\r
11575 } else // for other browsers, just ajax the content down in parallel, and use\r
11576 // globalEval to serialize evaluation\r
11577 {\r
11578 me.fetch({\r
11579 async: !sync,\r
11580 complete: function(response) {\r
11581 me.onContentLoaded(response);\r
11582 me.notifyRequests();\r
11583 }\r
11584 });\r
11585 }\r
11586 } else // for sync mode in js, global eval FTW. IE won't honor the comment\r
11587 // paths in the debugger, so eventually we need a sync mode for IE that\r
11588 // uses the readyStateChange mechanism\r
11589 {\r
11590 me.loadSync();\r
11591 }\r
11592 }\r
11593 // signal that the load process can continue\r
11594 return true;\r
11595 },\r
11596 evaluateContent: function() {\r
11597 this.inject(this.content);\r
11598 this.content = null;\r
11599 },\r
11600 evaluateLoadElement: function() {\r
11601 Boot.getHead().appendChild(this.getElement());\r
11602 },\r
11603 evaluate: function() {\r
11604 var me = this;\r
11605 if (!me.evaluated) {\r
11606 if (me.evaluating) {\r
11607 return;\r
11608 }\r
11609 me.evaluating = true;\r
11610 if (me.content !== undefined) {\r
11611 me.evaluateContent();\r
11612 } else if (!me.error) {\r
11613 me.evaluateLoadElement();\r
11614 }\r
11615 me.evaluated = me.done = true;\r
11616 me.cleanup();\r
11617 }\r
11618 },\r
11619 /*
11620 * @private
11621 */\r
11622 cleanup: function() {\r
11623 var me = this,\r
11624 el = me.el,\r
11625 prop;\r
11626 if (!el) {\r
11627 return;\r
11628 }\r
11629 if (!me.preserve) {\r
11630 me.el = null;\r
11631 el.parentNode.removeChild(el);\r
11632 // Remove, since its useless now\r
11633 for (prop in el) {\r
11634 try {\r
11635 if (prop !== me.prop) {\r
11636 // If we set the src property to null IE\r
11637 // will try and request a script at './null'\r
11638 el[prop] = null;\r
11639 }\r
11640 delete el[prop];\r
11641 } // and prepare for GC\r
11642 catch (cleanEx) {}\r
11643 }\r
11644 }\r
11645 //ignore\r
11646 // Setting to null can cause exceptions if IE ever needs to call these\r
11647 // again (like onreadystatechange). This emptyFn has nothing locked in\r
11648 // closure scope so it is about as safe as null for memory leaks.\r
11649 el.onload = el.onerror = el.onreadystatechange = emptyFn;\r
11650 },\r
11651 notifyRequests: function() {\r
11652 var requests = this.requests,\r
11653 len = requests.length,\r
11654 i, request;\r
11655 for (i = 0; i < len; i++) {\r
11656 request = requests[i];\r
11657 request.processLoadedEntries();\r
11658 }\r
11659 if (this.done) {\r
11660 this.fireListeners();\r
11661 }\r
11662 },\r
11663 onDone: function(listener) {\r
11664 var me = this,\r
11665 listeners = me.listeners || (me.listeners = []);\r
11666 if (me.done) {\r
11667 listener(me);\r
11668 } else {\r
11669 listeners.push(listener);\r
11670 }\r
11671 },\r
11672 fireListeners: function() {\r
11673 var listeners = this.listeners,\r
11674 listener;\r
11675 if (listeners && listeners.length > 0) {\r
11676 _debug("firing event listeners for url " + this.url);\r
11677 while ((listener = listeners.shift())) {\r
11678 listener(this);\r
11679 }\r
11680 }\r
11681 }\r
11682 };\r
11683 /*
11684 * Turns on or off the "cache buster" applied to dynamically loaded scripts. Normally
11685 * dynamically loaded scripts have an extra query parameter appended to avoid stale
11686 * cached scripts. This method can be used to disable this mechanism, and is primarily
11687 * useful for testing. This is done using a cookie.
11688 * @param {Boolean} disable True to disable the cache buster.
11689 * @param {String} [path="/"] An optional path to scope the cookie.
11690 */\r
11691 Ext.disableCacheBuster = function(disable, path) {\r
11692 var date = new Date();\r
11693 date.setTime(date.getTime() + (disable ? 10 * 365 : -1) * 24 * 60 * 60 * 1000);\r
11694 date = date.toGMTString();\r
11695 doc.cookie = 'ext-cache=1; expires=' + date + '; path=' + (path || '/');\r
11696 };\r
11697 Boot.init();\r
11698 return Boot;\r
11699}(// NOTE: We run the eval at global scope to protect the body of the function and allow\r
11700// compressors to still process it.\r
11701function() {}));\r
11702//(eval("/*@cc_on!@*/!1"));\r
11703/*
11704 * This method evaluates the given code free of any local variable. This
11705 * will be at global scope, in others it will be in a function.
11706 * @parma {String} code The code to evaluate.
11707 * @private
11708 * @method
11709 */\r
11710Ext.globalEval = Ext.globalEval || (this.execScript ? function(code) {\r
11711 execScript(code);\r
11712} : function($$code) {\r
11713 eval.call(window, $$code);\r
11714});\r
11715/*
11716 * Only IE8 & IE/Quirks lack Function.prototype.bind so we polyfill that here.
11717 */\r
11718if (!Function.prototype.bind) {\r
11719 (function() {\r
11720 var slice = Array.prototype.slice,\r
11721 // To reduce overhead on call of the bound fn we have two flavors based on\r
11722 // whether we have args to prepend or not:\r
11723 bind = function(me) {\r
11724 var args = slice.call(arguments, 1),\r
11725 method = this;\r
11726 if (args.length) {\r
11727 return function() {\r
11728 var t = arguments;\r
11729 // avoid the slice/concat if the caller does not supply args\r
11730 return method.apply(me, t.length ? args.concat(slice.call(t)) : args);\r
11731 };\r
11732 }\r
11733 // this is the majority use case - just fn.bind(this) and no args\r
11734 args = null;\r
11735 return function() {\r
11736 return method.apply(me, arguments);\r
11737 };\r
11738 };\r
11739 Function.prototype.bind = bind;\r
11740 bind.$extjs = true;\r
11741 }());\r
11742}\r
11743// to detect this polyfill if one want to improve it\r
11744//</editor-fold>\r
11745Ext.setResourcePath = function(poolName, path) {\r
11746 var manifest = Ext.manifest || (Ext.manifest = {}),\r
11747 paths = manifest.resources || (manifest.resources = {});\r
11748 if (manifest) {\r
11749 if (typeof poolName !== 'string') {\r
11750 Ext.apply(paths, poolName);\r
11751 } else {\r
11752 paths[poolName] = path;\r
11753 }\r
11754 manifest.resources = paths;\r
11755 }\r
11756};\r
11757Ext.getResourcePath = function(path, poolName, packageName) {\r
11758 if (typeof path !== 'string') {\r
11759 poolName = path.pool;\r
11760 packageName = path.packageName;\r
11761 path = path.path;\r
11762 }\r
11763 var manifest = Ext.manifest,\r
11764 paths = manifest && manifest.resources,\r
11765 poolPath = paths[poolName],\r
11766 output = [];\r
11767 if (poolPath == null) {\r
11768 poolPath = paths.path;\r
11769 if (poolPath == null) {\r
11770 poolPath = 'resources';\r
11771 }\r
11772 }\r
11773 if (poolPath) {\r
11774 output.push(poolPath);\r
11775 }\r
11776 if (packageName) {\r
11777 output.push(packageName);\r
11778 }\r
11779 output.push(path);\r
11780 return output.join('/');\r
11781};\r
11782\r
11783// @tag core\r
11784/**
11785 * @class Ext
11786 *
11787 * The Ext namespace (global object) encapsulates all classes, singletons, and
11788 * utility methods provided by Sencha's libraries.
11789 *
11790 * Most user interface Components are at a lower level of nesting in the namespace,
11791 * but many common utility functions are provided as direct properties of the Ext namespace.
11792 *
11793 * Also many frequently used methods from other classes are provided as shortcuts
11794 * within the Ext namespace. For example {@link Ext#getCmp Ext.getCmp} aliases
11795 * {@link Ext.ComponentManager#get Ext.ComponentManager.get}.
11796 *
11797 * Many applications are initiated with {@link Ext#application Ext.application} which is
11798 * called once the DOM is ready. This ensures all scripts have been loaded, preventing
11799 * dependency issues. For example:
11800 *
11801 * Ext.application({
11802 * name: 'MyApp',
11803 *
11804 * launch: function () {
11805 * Ext.Msg.alert(this.name, 'Ready to go!');
11806 * }
11807 * });
11808 *
11809 * <b><a href="http://www.sencha.com/products/sencha-cmd/">Sencha Cmd</a></b> is a free tool
11810 * for helping you generate and build Ext JS (and Sencha Touch) applications. See
11811 * `{@link Ext.app.Application Application}` for more information about creating an app.
11812 *
11813 * A lower-level technique that does not use the `Ext.app.Application` architecture is
11814 * {@link Ext#onReady Ext.onReady}.
11815 *
11816 * For more information about how to use the Ext classes, see:
11817 *
11818 * - <a href="http://www.sencha.com/learn/">The Learning Center</a>
11819 * - <a href="http://www.sencha.com/learn/Ext_FAQ">The FAQ</a>
11820 * - <a href="http://www.sencha.com/forum/">The forums</a>
11821 *
11822 * @singleton
11823 */\r
11824var Ext = Ext || {};\r
11825// jshint ignore:line\r
11826// @define Ext\r
11827(function() {\r
11828 var global = this,\r
11829 objectPrototype = Object.prototype,\r
11830 toString = objectPrototype.toString,\r
11831 enumerables = [\r
11832 //'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\r
11833 'valueOf',\r
11834 'toLocaleString',\r
11835 'toString',\r
11836 'constructor'\r
11837 ],\r
11838 emptyFn = function() {},\r
11839 privateFn = function() {},\r
11840 identityFn = function(o) {\r
11841 return o;\r
11842 },\r
11843 // This is the "$previous" method of a hook function on an instance. When called, it\r
11844 // calls through the class prototype by the name of the called method.\r
11845 callOverrideParent = function() {\r
11846 var method = callOverrideParent.caller.caller;\r
11847 // skip callParent (our caller)\r
11848 return method.$owner.prototype[method.$name].apply(this, arguments);\r
11849 },\r
11850 manifest = Ext.manifest || {},\r
11851 i,\r
11852 iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|HTML\s+document\.all\s+class)\]/,\r
11853 MSDateRe = /^\\?\/Date\(([-+])?(\d+)(?:[+-]\d{4})?\)\\?\/$/;\r
11854 Ext.global = global;\r
11855 /**
11856 * Returns the current timestamp.
11857 * @return {Number} Milliseconds since UNIX epoch.
11858 * @method now
11859 * @member Ext
11860 */\r
11861 Ext.now = Date.now || (Date.now = function() {\r
11862 return +new Date();\r
11863 });\r
11864 /**
11865 * Returns the current high-resolution timestamp.
11866 * @return {Number} Milliseconds ellapsed since arbitrary epoch.
11867 * @method ticks
11868 * @member Ext
11869 * @since 6.0.1
11870 */\r
11871 Ext.ticks = (global.performance && global.performance.now) ? function() {\r
11872 return performance.now();\r
11873 } : // jshint ignore:line\r
11874 Ext.now;\r
11875 Ext._startTime = Ext.ticks();\r
11876 // Mark these special fn's for easy identification:\r
11877 emptyFn.$nullFn = identityFn.$nullFn = emptyFn.$emptyFn = identityFn.$identityFn = privateFn.$nullFn = true;\r
11878 privateFn.$privacy = 'framework';\r
11879 // These are emptyFn's in core and are redefined only in Ext JS (we use this syntax\r
11880 // so Cmd does not detect them):\r
11881 Ext['suspendLayouts'] = Ext['resumeLayouts'] = emptyFn;\r
11882 // jshint ignore:line\r
11883 for (i in {\r
11884 toString: 1\r
11885 }) {\r
11886 enumerables = null;\r
11887 }\r
11888 /**
11889 * An array containing extra enumerables for old browsers
11890 * @property {String[]}
11891 */\r
11892 Ext.enumerables = enumerables;\r
11893 /**
11894 * Copies all the properties of `config` to the specified `object`. There are two levels
11895 * of defaulting supported:
11896 *
11897 * Ext.apply(obj, { a: 1 }, { a: 2 });
11898 * //obj.a === 1
11899 *
11900 * Ext.apply(obj, { }, { a: 2 });
11901 * //obj.a === 2
11902 *
11903 * Note that if recursive merging and cloning without referencing the original objects
11904 * or arrays is needed, use {@link Ext.Object#merge} instead.
11905 *
11906 * @param {Object} object The receiver of the properties.
11907 * @param {Object} config The primary source of the properties.
11908 * @param {Object} [defaults] An object that will also be applied for default values.
11909 * @return {Object} returns `object`.
11910 */\r
11911 Ext.apply = function(object, config, defaults) {\r
11912 if (defaults) {\r
11913 Ext.apply(object, defaults);\r
11914 }\r
11915 if (object && config && typeof config === 'object') {\r
11916 var i, j, k;\r
11917 for (i in config) {\r
11918 object[i] = config[i];\r
11919 }\r
11920 if (enumerables) {\r
11921 for (j = enumerables.length; j--; ) {\r
11922 k = enumerables[j];\r
11923 if (config.hasOwnProperty(k)) {\r
11924 object[k] = config[k];\r
11925 }\r
11926 }\r
11927 }\r
11928 }\r
11929 return object;\r
11930 };\r
11931 // Used by Ext.override\r
11932 function addInstanceOverrides(target, owner, overrides) {\r
11933 var name, value;\r
11934 for (name in overrides) {\r
11935 if (overrides.hasOwnProperty(name)) {\r
11936 value = overrides[name];\r
11937 if (typeof value === 'function') {\r
11938 if (owner.$className) {\r
11939 value.name = owner.$className + '#' + name;\r
11940 }\r
11941 value.$name = name;\r
11942 value.$owner = owner;\r
11943 value.$previous = target.hasOwnProperty(name) ? target[name] : // already hooked, so call previous hook\r
11944 callOverrideParent;\r
11945 }\r
11946 // calls by name on prototype\r
11947 target[name] = value;\r
11948 }\r
11949 }\r
11950 }\r
11951 Ext.buildSettings = Ext.apply({\r
11952 baseCSSPrefix: 'x-'\r
11953 }, Ext.buildSettings || {});\r
11954 Ext.apply(Ext, {\r
11955 /**
11956 * @private
11957 */\r
11958 idSeed: 0,\r
11959 /**
11960 * @private
11961 */\r
11962 idPrefix: 'ext-',\r
11963 /**
11964 * @property {Boolean} isSecure
11965 * True if the page is running over SSL
11966 * @readonly
11967 */\r
11968 isSecure: /^https/i.test(window.location.protocol),\r
11969 /**
11970 * `true` to automatically uncache orphaned Ext.Elements periodically. If set to
11971 * `false`, the application will be required to clean up orphaned Ext.Elements and
11972 * it's listeners as to not cause memory leakage.
11973 */\r
11974 enableGarbageCollector: false,\r
11975 /**
11976 * True to automatically purge event listeners during garbageCollection.
11977 */\r
11978 enableListenerCollection: true,\r
11979 /**
11980 * @property {String} [name='Ext']
11981 * <p>The name of the property in the global namespace (The <code>window</code> in browser environments) which refers to the current instance of Ext.</p>
11982 * <p>This is usually <code>"Ext"</code>, but if a sandboxed build of ExtJS is being used, this will be an alternative name.</p>
11983 * <p>If code is being generated for use by <code>eval</code> or to create a <code>new Function</code>, and the global instance
11984 * of Ext must be referenced, this is the name that should be built into the code.</p>
11985 */\r
11986 name: Ext.sandboxName || 'Ext',\r
11987 /**
11988 * @property {Function}
11989 * A reusable empty function for use as `privates` members.
11990 *
11991 * Ext.define('MyClass', {
11992 * nothing: Ext.emptyFn,
11993 *
11994 * privates: {
11995 * privateNothing: Ext.privateFn
11996 * }
11997 * });
11998 *
11999 */\r
12000 privateFn: privateFn,\r
12001 /**
12002 * @property {Function}
12003 * A reusable empty function.
12004 */\r
12005 emptyFn: emptyFn,\r
12006 /**
12007 * @property {Function}
12008 * A reusable identity function that simply returns its first argument.
12009 */\r
12010 identityFn: identityFn,\r
12011 /**
12012 * This indicate the start timestamp of current cycle.
12013 * It is only reliable during dom-event-initiated cycles and
12014 * {@link Ext.draw.Animator} initiated cycles.
12015 */\r
12016 frameStartTime: Ext.now(),\r
12017 /**
12018 * This object is initialized prior to loading the framework (Ext JS or Sencha
12019 * Touch) and contains settings and other information describing the application.
12020 *
12021 * For applications built using Sencha Cmd, this is produced from the `"app.json"`
12022 * file with information extracted from all of the required packages' `"package.json"`
12023 * files. This can be set to a string when your application is using the
12024 * (microloader)[#/guide/microloader]. In this case, the string of "foo" will be
12025 * requested as `"foo.json"` and the object in that JSON file will parsed and set
12026 * as this object.
12027 *
12028 * @cfg {String/Object} manifest
12029 *
12030 * @cfg {String/Object} manifest.compatibility An object keyed by package name with
12031 * the value being to desired compatibility level as a version number. If this is
12032 * just a string, this version is assumed to apply to the framework ('ext' or
12033 * 'touch'). Setting this value to less than 5 for 'ext' will enable the compatibility
12034 * layer to assist in the application upgrade process. For details on the upgrade
12035 * process, see the (Upgrade Guide)[#/guides/upgrade_50].
12036 *
12037 * @cfg {Object} manifest.debug An object configuring the debugging characteristics
12038 * of the framework. See `Ext.debugConfig` which is set to this value.
12039 *
12040 * @cfg {Object} manifest.packages An object keyed by package name with the value
12041 * being a subset of the package's `"package.json"` descriptor.
12042 * @since 5.0.0
12043 */\r
12044 manifest: manifest,\r
12045 /**
12046 * @cfg {Object} [debugConfig]
12047 * This object is used to enable or disable debugging for classes or namespaces. The
12048 * default instance looks like this:
12049 *
12050 * Ext.debugConfig = {
12051 * hooks: {
12052 * '*': true
12053 * }
12054 * };
12055 *
12056 * Typically applications will set this in their `"app.json"` like so:
12057 *
12058 * {
12059 * "debug": {
12060 * "hooks": {
12061 * // Default for all namespaces:
12062 * '*': true,
12063 *
12064 * // Except for Ext namespace which is disabled
12065 * 'Ext': false,
12066 *
12067 * // Except for Ext.layout namespace which is enabled
12068 * 'Ext.layout': true
12069 * }
12070 * }
12071 * }
12072 *
12073 * Alternatively, because this property is consumed very early in the load process of
12074 * the framework, this can be set in a `script` tag that is defined prior to loading
12075 * the framework itself.
12076 *
12077 * For example, to enable debugging for the `Ext.layout` namespace only:
12078 *
12079 * var Ext = Ext || {};
12080 * Ext.debugConfig = {
12081 * hooks: {
12082 * //...
12083 * }
12084 * };
12085 *
12086 * For any class declared, the longest matching namespace specified determines if its
12087 * `debugHooks` will be enabled. The default setting is specified by the '*' property.
12088 *
12089 * **NOTE:** This option only applies to debug builds. All debugging is disabled in
12090 * production builds.
12091 */\r
12092 debugConfig: Ext.debugConfig || manifest.debug || {\r
12093 hooks: {\r
12094 '*': true\r
12095 }\r
12096 },\r
12097 /**
12098 * @property {Boolean} [enableAria=true] This property is provided for backward
12099 * compatibility with previous versions of Ext JS. Accessibility is always enabled
12100 * in Ext JS 6.0+
12101 * @since 6.0.0
12102 */\r
12103 enableAria: true,\r
12104 /**
12105 * @property {Boolean} [enableAriaButtons=true] Set to `false` to disable WAI-ARIA
12106 * compatibility checks for buttons.
12107 * @since 6.0.0
12108 */\r
12109 enableAriaButtons: true,\r
12110 /**
12111 * @property {Boolean} [enableAriaPanels=true] Set to `false` to disable WAI-ARIA
12112 * compatibility checks for panels.
12113 * @since 6.0.0
12114 */\r
12115 enableAriaPanels: true,\r
12116 startsWithHashRe: /^#/,\r
12117 /**
12118 * @property {RegExp}
12119 * @private
12120 * Regular expression used for validating identifiers.
12121 */\r
12122 validIdRe: /^[a-z_][a-z0-9\-_]*$/i,\r
12123 /**
12124 * @property {String} BLANK_IMAGE_URL
12125 * URL to a 1x1 transparent gif image used by Ext to create inline icons with
12126 * CSS background images.
12127 */\r
12128 BLANK_IMAGE_URL: 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',\r
12129 /**
12130 * Converts an id (`'foo'`) into an id selector (`'#foo'`). This method is used
12131 * internally by the framework whenever an id needs to be converted into a selector
12132 * and is provided as a hook for those that need to escape IDs selectors since,
12133 * as of Ext 5.0, the framework no longer escapes IDs by default.
12134 * @private
12135 * @param {String} id
12136 * @return {String}
12137 */\r
12138 makeIdSelector: function(id) {\r
12139 if (!Ext.validIdRe.test(id)) {\r
12140 Ext.raise('Invalid id selector: "' + id + '"');\r
12141 }\r
12142 return '#' + id;\r
12143 },\r
12144 /**
12145 * Generates unique ids. If the object/element is passes and it already has an `id`, it is unchanged.
12146 * @param {Object} [o] The object to generate an id for.
12147 * @param {String} [prefix=ext-gen] (optional) The `id` prefix.
12148 * @return {String} The generated `id`.
12149 */\r
12150 id: function(o, prefix) {\r
12151 if (o && o.id) {\r
12152 return o.id;\r
12153 }\r
12154 var id = (prefix || Ext.idPrefix) + (++Ext.idSeed);\r
12155 if (o) {\r
12156 o.id = id;\r
12157 }\r
12158 return id;\r
12159 },\r
12160 /**
12161 * A reusable function which returns the value of `getId()` called upon a single passed parameter.
12162 * Useful when creating a {@link Ext.util.MixedCollection} of objects keyed by an identifier returned from a `getId` method.
12163 */\r
12164 returnId: function(o) {\r
12165 return o.getId();\r
12166 },\r
12167 /**
12168 * A reusable function which returns `true`.
12169 */\r
12170 returnTrue: function() {\r
12171 return true;\r
12172 },\r
12173 /**
12174 * A zero length string which will pass a truth test. Useful for passing to methods
12175 * which use a truth test to reject <i>falsy</i> values where a string value must be cleared.
12176 */\r
12177 emptyString: new String(),\r
12178 // jshint ignore:line\r
12179 /**
12180 * @property {String} [baseCSSPrefix='x-']
12181 * The base prefix to use for all `Ext` components. To configure this property, you should use the
12182 * Ext.buildSettings object before the framework is loaded:
12183 *
12184 * Ext.buildSettings = {
12185 * baseCSSPrefix : 'abc-'
12186 * };
12187 *
12188 * or you can change it before any components are rendered:
12189 *
12190 * Ext.baseCSSPrefix = Ext.buildSettings.baseCSSPrefix = 'abc-';
12191 *
12192 * This will change what CSS classes components will use and you should
12193 * then recompile the SASS changing the `$prefix` SASS variable to match.
12194 */\r
12195 baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,\r
12196 /**
12197 * @property {Object} $eventNameMap
12198 * A map of event names which contained the lower-cased versions of any mixed
12199 * case event names.
12200 * @private
12201 */\r
12202 $eventNameMap: {},\r
12203 // Vendor-specific events do not work if lower-cased. This regex specifies event\r
12204 // prefixes for names that should NOT be lower-cased by Ext.canonicalEventName()\r
12205 $vendorEventRe: /^(Moz.+|MS.+|webkit.+)/,\r
12206 // TODO: inlinable function - SDKTOOLS-686\r
12207 /**
12208 * @private
12209 * @inline
12210 */\r
12211 canonicalEventName: function(name) {\r
12212 return Ext.$eventNameMap[name] || (Ext.$eventNameMap[name] = (Ext.$vendorEventRe.test(name) ? name : name.toLowerCase()));\r
12213 },\r
12214 /**
12215 * Copies all the properties of config to object if they don't already exist.
12216 * @param {Object} object The receiver of the properties
12217 * @param {Object} config The source of the properties
12218 * @return {Object} returns obj
12219 */\r
12220 applyIf: function(object, config) {\r
12221 var property;\r
12222 if (object) {\r
12223 for (property in config) {\r
12224 if (object[property] === undefined) {\r
12225 object[property] = config[property];\r
12226 }\r
12227 }\r
12228 }\r
12229 return object;\r
12230 },\r
12231 /**
12232 * Destroys all of the given objects. If arrays are passed, the elements of these
12233 * are destroyed recursively.
12234 *
12235 * What it means to "destroy" an object depends on the type of object.
12236 *
12237 * * `Array`: Each element of the array is destroyed recursively.
12238 * * `Object`: Any object with a `destroy` method will have that method called.
12239 *
12240 * @param {Mixed...} args Any number of objects or arrays.
12241 */\r
12242 destroy: function() {\r
12243 var ln = arguments.length,\r
12244 i, arg;\r
12245 for (i = 0; i < ln; i++) {\r
12246 arg = arguments[i];\r
12247 if (arg) {\r
12248 if (Ext.isArray(arg)) {\r
12249 this.destroy.apply(this, arg);\r
12250 } else if (Ext.isFunction(arg.destroy)) {\r
12251 arg.destroy();\r
12252 }\r
12253 }\r
12254 }\r
12255 return null;\r
12256 },\r
12257 /**
12258 * Destroys the specified named members of the given object using `Ext.destroy`. These
12259 * properties will be set to `null`.
12260 * @param {Object} object The object who's properties you wish to destroy.
12261 * @param {String...} args One or more names of the properties to destroy and remove from the object.
12262 */\r
12263 destroyMembers: function(object) {\r
12264 for (var ref, name,\r
12265 i = 1,\r
12266 a = arguments,\r
12267 len = a.length; i < len; i++) {\r
12268 ref = object[name = a[i]];\r
12269 // Avoid adding the property if it does not already exist\r
12270 if (ref != null) {\r
12271 object[name] = Ext.destroy(ref);\r
12272 }\r
12273 }\r
12274 },\r
12275 /**
12276 * Overrides members of the specified `target` with the given values.
12277 *
12278 * If the `target` is a class declared using {@link Ext#define Ext.define}, the
12279 * `override` method of that class is called (see {@link Ext.Base#override}) given
12280 * the `overrides`.
12281 *
12282 * If the `target` is a function, it is assumed to be a constructor and the contents
12283 * of `overrides` are applied to its `prototype` using {@link Ext#apply Ext.apply}.
12284 *
12285 * If the `target` is an instance of a class declared using {@link Ext#define Ext.define},
12286 * the `overrides` are applied to only that instance. In this case, methods are
12287 * specially processed to allow them to use {@link Ext.Base#callParent}.
12288 *
12289 * var panel = new Ext.Panel({ ... });
12290 *
12291 * Ext.override(panel, {
12292 * initComponent: function () {
12293 * // extra processing...
12294 *
12295 * this.callParent();
12296 * }
12297 * });
12298 *
12299 * If the `target` is none of these, the `overrides` are applied to the `target`
12300 * using {@link Ext#apply Ext.apply}.
12301 *
12302 * Please refer to {@link Ext#define Ext.define} and {@link Ext.Base#override} for
12303 * further details.
12304 *
12305 * @param {Object} target The target to override.
12306 * @param {Object} overrides The properties to add or replace on `target`.
12307 * @method override
12308 */\r
12309 override: function(target, overrides) {\r
12310 if (target.$isClass) {\r
12311 target.override(overrides);\r
12312 } else if (typeof target === 'function') {\r
12313 Ext.apply(target.prototype, overrides);\r
12314 } else {\r
12315 var owner = target.self,\r
12316 privates;\r
12317 if (owner && owner.$isClass) {\r
12318 // if (instance of Ext.define'd class)\r
12319 privates = overrides.privates;\r
12320 if (privates) {\r
12321 overrides = Ext.apply({}, overrides);\r
12322 delete overrides.privates;\r
12323 addInstanceOverrides(target, owner, privates);\r
12324 }\r
12325 addInstanceOverrides(target, owner, overrides);\r
12326 } else {\r
12327 Ext.apply(target, overrides);\r
12328 }\r
12329 }\r
12330 return target;\r
12331 },\r
12332 /**
12333 * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default
12334 * value (second argument) otherwise.
12335 *
12336 * @param {Object} value The value to test.
12337 * @param {Object} defaultValue The value to return if the original value is empty.
12338 * @param {Boolean} [allowBlank=false] `true` to allow zero length strings to qualify as non-empty.
12339 * @return {Object} value, if non-empty, else defaultValue.
12340 */\r
12341 valueFrom: function(value, defaultValue, allowBlank) {\r
12342 return Ext.isEmpty(value, allowBlank) ? defaultValue : value;\r
12343 },\r
12344 /**
12345 * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if it is either:
12346 *
12347 * - `null`
12348 * - `undefined`
12349 * - a zero-length array
12350 * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`)
12351 *
12352 * @param {Object} value The value to test.
12353 * @param {Boolean} [allowEmptyString=false] `true` to allow empty strings.
12354 * @return {Boolean}
12355 */\r
12356 isEmpty: function(value, allowEmptyString) {\r
12357 return (value == null) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);\r
12358 },\r
12359 /**
12360 * Returns `true` if the passed value is a JavaScript Array, `false` otherwise.
12361 *
12362 * @param {Object} target The target to test.
12363 * @return {Boolean}
12364 * @method
12365 */\r
12366 isArray: ('isArray' in Array) ? Array.isArray : function(value) {\r
12367 return toString.call(value) === '[object Array]';\r
12368 },\r
12369 /**
12370 * Returns `true` if the passed value is a JavaScript Date object, `false` otherwise.
12371 * @param {Object} object The object to test.
12372 * @return {Boolean}
12373 */\r
12374 isDate: function(value) {\r
12375 return toString.call(value) === '[object Date]';\r
12376 },\r
12377 /**
12378 * Returns 'true' if the passed value is a String that matches the MS Date JSON
12379 * encoding format.
12380 * @param {String} value The string to test.
12381 * @return {Boolean}
12382 */\r
12383 isMSDate: function(value) {\r
12384 if (!Ext.isString(value)) {\r
12385 return false;\r
12386 }\r
12387 return MSDateRe.test(value);\r
12388 },\r
12389 /**
12390 * Returns `true` if the passed value is a JavaScript Object, `false` otherwise.
12391 * @param {Object} value The value to test.
12392 * @return {Boolean}
12393 * @method
12394 */\r
12395 isObject: (toString.call(null) === '[object Object]') ? function(value) {\r
12396 // check ownerDocument here as well to exclude DOM nodes\r
12397 return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;\r
12398 } : function(value) {\r
12399 return toString.call(value) === '[object Object]';\r
12400 },\r
12401 /**
12402 * @private
12403 */\r
12404 isSimpleObject: function(value) {\r
12405 return value instanceof Object && value.constructor === Object;\r
12406 },\r
12407 /**
12408 * Returns `true` if the passed value is a JavaScript 'primitive', a string, number
12409 * or boolean.
12410 * @param {Object} value The value to test.
12411 * @return {Boolean}
12412 */\r
12413 isPrimitive: function(value) {\r
12414 var type = typeof value;\r
12415 return type === 'string' || type === 'number' || type === 'boolean';\r
12416 },\r
12417 /**
12418 * Returns `true` if the passed value is a JavaScript Function, `false` otherwise.
12419 * @param {Object} value The value to test.
12420 * @return {Boolean}
12421 * @method
12422 */\r
12423 isFunction: // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using\r
12424 // Object.prototype.toString (slower)\r
12425 (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {\r
12426 return !!value && toString.call(value) === '[object Function]';\r
12427 } : function(value) {\r
12428 return !!value && typeof value === 'function';\r
12429 },\r
12430 /**
12431 * Returns `true` if the passed value is a number. Returns `false` for non-finite numbers.
12432 * @param {Object} value The value to test.
12433 * @return {Boolean}
12434 */\r
12435 isNumber: function(value) {\r
12436 return typeof value === 'number' && isFinite(value);\r
12437 },\r
12438 /**
12439 * Validates that a value is numeric.
12440 * @param {Object} value Examples: 1, '1', '2.34'
12441 * @return {Boolean} True if numeric, false otherwise
12442 */\r
12443 isNumeric: function(value) {\r
12444 return !isNaN(parseFloat(value)) && isFinite(value);\r
12445 },\r
12446 /**
12447 * Returns `true `if the passed value is a string.
12448 * @param {Object} value The value to test.
12449 * @return {Boolean}
12450 */\r
12451 isString: function(value) {\r
12452 return typeof value === 'string';\r
12453 },\r
12454 /**
12455 * Returns `true` if the passed value is a boolean.
12456 *
12457 * @param {Object} value The value to test.
12458 * @return {Boolean}
12459 */\r
12460 isBoolean: function(value) {\r
12461 return typeof value === 'boolean';\r
12462 },\r
12463 /**
12464 * Returns `true` if the passed value is an HTMLElement
12465 * @param {Object} value The value to test.
12466 * @return {Boolean}
12467 */\r
12468 isElement: function(value) {\r
12469 return value ? value.nodeType === 1 : false;\r
12470 },\r
12471 /**
12472 * Returns `true` if the passed value is a TextNode
12473 * @param {Object} value The value to test.
12474 * @return {Boolean}
12475 */\r
12476 isTextNode: function(value) {\r
12477 return value ? value.nodeName === "#text" : false;\r
12478 },\r
12479 /**
12480 * Returns `true` if the passed value is defined.
12481 * @param {Object} value The value to test.
12482 * @return {Boolean}
12483 */\r
12484 isDefined: function(value) {\r
12485 return typeof value !== 'undefined';\r
12486 },\r
12487 /**
12488 * Returns `true` if the passed value is iterable, that is, if elements of it are addressable using array
12489 * notation with numeric indices, `false` otherwise.
12490 *
12491 * Arrays and function `arguments` objects are iterable. Also HTML collections such as `NodeList` and `HTMLCollection'
12492 * are iterable.
12493 *
12494 * @param {Object} value The value to test
12495 * @return {Boolean}
12496 */\r
12497 isIterable: function(value) {\r
12498 // To be iterable, the object must have a numeric length property and must not be a string or function.\r
12499 if (!value || typeof value.length !== 'number' || typeof value === 'string' || Ext.isFunction(value)) {\r
12500 return false;\r
12501 }\r
12502 // Certain "standard" collections in IE (such as document.images) do not offer the correct\r
12503 // Javascript Object interface; specifically, they lack the propertyIsEnumerable method.\r
12504 // And the item property while it does exist is not typeof "function"\r
12505 if (!value.propertyIsEnumerable) {\r
12506 return !!value.item;\r
12507 }\r
12508 // If it is a regular, interrogatable JS object (not an IE ActiveX object), then...\r
12509 // If it has its own property called "length", but not enumerable, it's iterable\r
12510 if (value.hasOwnProperty('length') && !value.propertyIsEnumerable('length')) {\r
12511 return true;\r
12512 }\r
12513 // Test against whitelist which includes known iterable collection types\r
12514 return iterableRe.test(toString.call(value));\r
12515 },\r
12516 /**
12517 * This method returns `true` if debug is enabled for the specified class. This is
12518 * done by checking the `Ext.debugConfig.hooks` config for the closest match to the
12519 * given `className`.
12520 * @param {String} className The name of the class.
12521 * @return {Boolean} `true` if debug is enabled for the specified class.
12522 */\r
12523 isDebugEnabled: function(className, defaultEnabled) {\r
12524 var debugConfig = Ext.debugConfig.hooks;\r
12525 if (debugConfig.hasOwnProperty(className)) {\r
12526 return debugConfig[className];\r
12527 }\r
12528 var enabled = debugConfig['*'],\r
12529 prefixLength = 0;\r
12530 if (defaultEnabled !== undefined) {\r
12531 enabled = defaultEnabled;\r
12532 }\r
12533 if (!className) {\r
12534 return enabled;\r
12535 }\r
12536 for (var prefix in debugConfig) {\r
12537 var value = debugConfig[prefix];\r
12538 // if prefix=='Ext' match 'Ext.foo.Bar' but not 'Ext4.foo.Bar'\r
12539 if (className.charAt(prefix.length) === '.') {\r
12540 if (className.substring(0, prefix.length) === prefix) {\r
12541 if (prefixLength < prefix.length) {\r
12542 prefixLength = prefix.length;\r
12543 enabled = value;\r
12544 }\r
12545 }\r
12546 }\r
12547 }\r
12548 return enabled;\r
12549 } || emptyFn,\r
12550 /**
12551 * Clone simple variables including array, {}-like objects, DOM nodes and Date without keeping the old reference.
12552 * A reference for the object itself is returned if it's not a direct descendant of Object. For model cloning,
12553 * see {@link Ext.data.Model#copy Model.copy}.
12554 *
12555 * @param {Object} item The variable to clone
12556 * @return {Object} clone
12557 */\r
12558 clone: function(item) {\r
12559 if (item === null || item === undefined) {\r
12560 return item;\r
12561 }\r
12562 // DOM nodes\r
12563 // TODO proxy this to Ext.Element.clone to handle automatic id attribute changing\r
12564 // recursively\r
12565 if (item.nodeType && item.cloneNode) {\r
12566 return item.cloneNode(true);\r
12567 }\r
12568 var type = toString.call(item),\r
12569 i, j, k, clone, key;\r
12570 // Date\r
12571 if (type === '[object Date]') {\r
12572 return new Date(item.getTime());\r
12573 }\r
12574 // Array\r
12575 if (type === '[object Array]') {\r
12576 i = item.length;\r
12577 clone = [];\r
12578 while (i--) {\r
12579 clone[i] = Ext.clone(item[i]);\r
12580 }\r
12581 }\r
12582 // Object\r
12583 else if (type === '[object Object]' && item.constructor === Object) {\r
12584 clone = {};\r
12585 for (key in item) {\r
12586 clone[key] = Ext.clone(item[key]);\r
12587 }\r
12588 if (enumerables) {\r
12589 for (j = enumerables.length; j--; ) {\r
12590 k = enumerables[j];\r
12591 if (item.hasOwnProperty(k)) {\r
12592 clone[k] = item[k];\r
12593 }\r
12594 }\r
12595 }\r
12596 }\r
12597 return clone || item;\r
12598 },\r
12599 /**
12600 * @private
12601 * Generate a unique reference of Ext in the global scope, useful for sandboxing
12602 */\r
12603 getUniqueGlobalNamespace: function() {\r
12604 var uniqueGlobalNamespace = this.uniqueGlobalNamespace,\r
12605 i;\r
12606 if (uniqueGlobalNamespace === undefined) {\r
12607 i = 0;\r
12608 do {\r
12609 uniqueGlobalNamespace = 'ExtBox' + (++i);\r
12610 } while (global[uniqueGlobalNamespace] !== undefined);\r
12611 global[uniqueGlobalNamespace] = Ext;\r
12612 this.uniqueGlobalNamespace = uniqueGlobalNamespace;\r
12613 }\r
12614 return uniqueGlobalNamespace;\r
12615 },\r
12616 /**
12617 * @private
12618 */\r
12619 functionFactoryCache: {},\r
12620 cacheableFunctionFactory: function() {\r
12621 var me = this,\r
12622 args = Array.prototype.slice.call(arguments),\r
12623 cache = me.functionFactoryCache,\r
12624 idx, fn, ln;\r
12625 if (Ext.isSandboxed) {\r
12626 ln = args.length;\r
12627 if (ln > 0) {\r
12628 ln--;\r
12629 args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];\r
12630 }\r
12631 }\r
12632 idx = args.join('');\r
12633 fn = cache[idx];\r
12634 if (!fn) {\r
12635 fn = Function.prototype.constructor.apply(Function.prototype, args);\r
12636 cache[idx] = fn;\r
12637 }\r
12638 return fn;\r
12639 },\r
12640 functionFactory: function() {\r
12641 var args = Array.prototype.slice.call(arguments),\r
12642 ln;\r
12643 if (Ext.isSandboxed) {\r
12644 ln = args.length;\r
12645 if (ln > 0) {\r
12646 ln--;\r
12647 args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];\r
12648 }\r
12649 }\r
12650 return Function.prototype.constructor.apply(Function.prototype, args);\r
12651 },\r
12652 /**
12653 * @private
12654 */\r
12655 Logger: {\r
12656 log: function(message, priority) {\r
12657 if (message && global.console) {\r
12658 if (!priority || !(priority in global.console)) {\r
12659 priority = 'log';\r
12660 }\r
12661 message = '[' + priority.toUpperCase() + '] ' + message;\r
12662 global.console[priority](message);\r
12663 }\r
12664 },\r
12665 verbose: function(message) {\r
12666 this.log(message, 'verbose');\r
12667 },\r
12668 info: function(message) {\r
12669 this.log(message, 'info');\r
12670 },\r
12671 warn: function(message) {\r
12672 this.log(message, 'warn');\r
12673 },\r
12674 error: function(message) {\r
12675 throw new Error(message);\r
12676 },\r
12677 deprecate: function(message) {\r
12678 this.log(message, 'warn');\r
12679 }\r
12680 } || {\r
12681 verbose: emptyFn,\r
12682 log: emptyFn,\r
12683 info: emptyFn,\r
12684 warn: emptyFn,\r
12685 error: function(message) {\r
12686 throw new Error(message);\r
12687 },\r
12688 deprecate: emptyFn\r
12689 },\r
12690 /**
12691 * @private
12692 */\r
12693 getElementById: function(id) {\r
12694 return document.getElementById(id);\r
12695 },\r
12696 /**
12697 * @member Ext
12698 * @private
12699 */\r
12700 splitAndUnescape: (function() {\r
12701 var cache = {};\r
12702 return function(origin, delimiter) {\r
12703 if (!origin) {\r
12704 return [];\r
12705 } else if (!delimiter) {\r
12706 return [\r
12707 origin\r
12708 ];\r
12709 }\r
12710 var replaceRe = cache[delimiter] || (cache[delimiter] = new RegExp('\\\\' + delimiter, 'g')),\r
12711 result = [],\r
12712 parts, part;\r
12713 parts = origin.split(delimiter);\r
12714 while ((part = parts.shift()) !== undefined) {\r
12715 // If any of the parts ends with the delimiter that means\r
12716 // the delimiter was escaped and the split was invalid. Roll back.\r
12717 while (part.charAt(part.length - 1) === '\\' && parts.length > 0) {\r
12718 part = part + delimiter + parts.shift();\r
12719 }\r
12720 // Now that we have split the parts, unescape the delimiter char\r
12721 part = part.replace(replaceRe, delimiter);\r
12722 result.push(part);\r
12723 }\r
12724 return result;\r
12725 };\r
12726 })()\r
12727 });\r
12728 // Ext.apply(Ext\r
12729 Ext.returnTrue.$nullFn = Ext.returnId.$nullFn = true;\r
12730}());\r
12731\r
12732// @override Ext\r
12733// This file is order extremely early (typically right after Ext.js) due to the\r
12734// above Cmd directive. This ensures that the "modern" and "classic" platform tags\r
12735// are properly set up as soon as possible.\r
12736Ext.platformTags.modern = !(Ext.platformTags.classic = Ext.isClassic = true);\r
12737\r
12738/**
12739 * A helper class for the native JavaScript Error object that adds a few useful capabilities for handling
12740 * errors in an application. When you use Ext.Error to {@link #raise} an error from within any class that
12741 * uses the Class System, the Error class can automatically add the source class and method from which
12742 * the error was raised. It also includes logic to automatically log the error to the console, if available,
12743 * with additional metadata about the error. In all cases, the error will always be thrown at the end so that
12744 * execution will halt.
12745 *
12746 * Ext.Error also offers a global error {@link #handle handling} method that can be overridden in order to
12747 * handle application-wide errors in a single spot. You can optionally {@link #ignore} errors altogether,
12748 * although in a real application it's usually a better idea to override the handling function and perform
12749 * logging or some other method of reporting the errors in a way that is meaningful to the application.
12750 *
12751 * At its simplest you can simply raise an error as a simple string from within any code:
12752 *
12753 * Example usage:
12754 *
12755 * Ext.raise('Something bad happened!');
12756 *
12757 * If raised from plain JavaScript code, the error will be logged to the console (if available) and the message
12758 * displayed. In most cases however you'll be raising errors from within a class, and it may often be useful to add
12759 * additional metadata about the error being raised. The {@link #raise} method can also take a config object.
12760 * In this form the `msg` attribute becomes the error description, and any other data added to the config gets
12761 * added to the error object and, if the console is available, logged to the console for inspection.
12762 *
12763 * Example usage:
12764 *
12765 * Ext.define('Ext.Foo', {
12766 * doSomething: function(option){
12767 * if (someCondition === false) {
12768 * Ext.raise({
12769 * msg: 'You cannot do that!',
12770 * option: option, // whatever was passed into the method
12771 * 'error code': 100 // other arbitrary info
12772 * });
12773 * }
12774 * }
12775 * });
12776 *
12777 * If a console is available (that supports the `console.dir` function) you'll see console output like:
12778 *
12779 * An error was raised with the following data:
12780 * option: Object { foo: "bar"}
12781 * foo: "bar"
12782 * error code: 100
12783 * msg: "You cannot do that!"
12784 * sourceClass: "Ext.Foo"
12785 * sourceMethod: "doSomething"
12786 *
12787 * uncaught exception: You cannot do that!
12788 *
12789 * As you can see, the error will report exactly where it was raised and will include as much information as the
12790 * raising code can usefully provide.
12791 *
12792 * If you want to handle all application errors globally you can simply override the static {@link #handle} method
12793 * and provide whatever handling logic you need. If the method returns true then the error is considered handled
12794 * and will not be thrown to the browser. If anything but true is returned then the error will be thrown normally.
12795 *
12796 * Example usage:
12797 *
12798 * Ext.Error.handle = function(err) {
12799 * if (err.someProperty == 'NotReallyAnError') {
12800 * // maybe log something to the application here if applicable
12801 * return true;
12802 * }
12803 * // any non-true return value (including none) will cause the error to be thrown
12804 * }
12805 *
12806 * @class Ext.Error
12807 */\r
12808(function() {\r
12809 // @define Ext.lang.Error\r
12810 // @define Ext.Error\r
12811 // @require Ext\r
12812 function toString() {\r
12813 var me = this,\r
12814 cls = me.sourceClass,\r
12815 method = me.sourceMethod,\r
12816 msg = me.msg;\r
12817 if (method) {\r
12818 if (msg) {\r
12819 method += '(): ';\r
12820 method += msg;\r
12821 } else {\r
12822 method += '()';\r
12823 }\r
12824 }\r
12825 if (cls) {\r
12826 method = method ? (cls + '.' + method) : cls;\r
12827 }\r
12828 return method || msg || '';\r
12829 }\r
12830 Ext.Error = function(config) {\r
12831 if (Ext.isString(config)) {\r
12832 config = {\r
12833 msg: config\r
12834 };\r
12835 }\r
12836 var error = new Error();\r
12837 Ext.apply(error, config);\r
12838 error.message = error.message || error.msg;\r
12839 // 'message' is standard ('msg' is non-standard)\r
12840 // note: the above does not work in old WebKit (me.message is readonly) (Safari 4)\r
12841 error.toString = toString;\r
12842 return error;\r
12843 };\r
12844 Ext.apply(Ext.Error, {\r
12845 /**
12846 * @property {Boolean} ignore
12847 * Static flag that can be used to globally disable error reporting to the browser if set to true
12848 * (defaults to false). Note that if you ignore Ext errors it's likely that some other code may fail
12849 * and throw a native JavaScript error thereafter, so use with caution. In most cases it will probably
12850 * be preferable to supply a custom error {@link #handle handling} function instead.
12851 *
12852 * Example usage:
12853 *
12854 * Ext.Error.ignore = true;
12855 *
12856 * @static
12857 */\r
12858 ignore: false,\r
12859 /**
12860 * This method is called internally by {@link Ext#raise}. Application code should
12861 * call {@link Ext#raise} instead of calling this method directly.
12862 *
12863 * @static
12864 * @deprecated 6.0.0 Use {@link Ext#raise} instead.
12865 */\r
12866 raise: function(err) {\r
12867 err = err || {};\r
12868 if (Ext.isString(err)) {\r
12869 err = {\r
12870 msg: err\r
12871 };\r
12872 }\r
12873 var me = this,\r
12874 method = me.raise.caller,\r
12875 msg, name;\r
12876 if (method === Ext.raise) {\r
12877 method = method.caller;\r
12878 }\r
12879 if (method) {\r
12880 if (!err.sourceMethod && (name = method.$name)) {\r
12881 err.sourceMethod = name;\r
12882 }\r
12883 if (!err.sourceClass && (name = method.$owner) && (name = name.$className)) {\r
12884 err.sourceClass = name;\r
12885 }\r
12886 }\r
12887 if (me.handle(err) !== true) {\r
12888 msg = toString.call(err);\r
12889 Ext.log({\r
12890 msg: msg,\r
12891 level: 'error',\r
12892 dump: err,\r
12893 stack: true\r
12894 });\r
12895 throw new Ext.Error(err);\r
12896 }\r
12897 },\r
12898 /**
12899 * Globally handle any Ext errors that may be raised, optionally providing custom logic to
12900 * handle different errors individually. Return true from the function to bypass throwing the
12901 * error to the browser, otherwise the error will be thrown and execution will halt.
12902 *
12903 * Example usage:
12904 *
12905 * Ext.Error.handle = function(err) {
12906 * if (err.someProperty == 'NotReallyAnError') {
12907 * // maybe log something to the application here if applicable
12908 * return true;
12909 * }
12910 * // any non-true return value (including none) will cause the error to be thrown
12911 * }
12912 *
12913 * @param {Object} err The error being raised. It will contain any attributes that were originally
12914 * raised with it, plus properties about the method and class from which the error originated
12915 * (if raised from a class that uses the Class System).
12916 * @static
12917 */\r
12918 handle: function() {\r
12919 return this.ignore;\r
12920 }\r
12921 });\r
12922})();\r
12923/**
12924 * Create a function that will throw an error if called (in debug mode) with a message that
12925 * indicates the method has been removed.
12926 * @param {String} suggestion Optional text to include in the message (a workaround perhaps).
12927 * @return {Function} The generated function.
12928 * @private
12929 */\r
12930Ext.deprecated = function(suggestion) {\r
12931 if (!suggestion) {\r
12932 suggestion = '';\r
12933 }\r
12934 function fail() {\r
12935 Ext.raise('The method "' + fail.$owner.$className + '.' + fail.$name + '" has been removed. ' + suggestion);\r
12936 }\r
12937 return fail;\r
12938 return Ext.emptyFn;\r
12939};\r
12940/**
12941 * Raise an error that can include additional data and supports automatic console logging
12942 * if available. You can pass a string error message or an object with the `msg` attribute
12943 * which will be used as the error message. The object can contain any other name-value
12944 * attributes (or objects) to be logged along with the error.
12945 *
12946 * Note that after displaying the error message a JavaScript error will ultimately be
12947 * thrown so that execution will halt.
12948 *
12949 * Example usage:
12950 *
12951 * Ext.raise('A simple string error message');
12952 *
12953 * // or...
12954 *
12955 * Ext.define('Ext.Foo', {
12956 * doSomething: function(option){
12957 * if (someCondition === false) {
12958 * Ext.raise({
12959 * msg: 'You cannot do that!',
12960 * option: option, // whatever was passed into the method
12961 * code: 100 // other arbitrary info
12962 * });
12963 * }
12964 * }
12965 * });
12966 *
12967 * @param {String/Object} err The error message string, or an object containing the
12968 * attribute "msg" that will be used as the error message. Any other data included in the
12969 * object will also be logged to the browser console, if available.
12970 * @method raise
12971 * @member Ext
12972 */\r
12973Ext.raise = function() {\r
12974 Ext.Error.raise.apply(Ext.Error, arguments);\r
12975};\r
12976/*
12977 * This mechanism is used to notify the user of the first error encountered on the page. In
12978 * most cases errors go unobserved especially on IE. This mechanism pushes this information
12979 * to the status bar so that users don't miss it.
12980 */\r
12981(function() {\r
12982 if (typeof window === 'undefined') {\r
12983 return;\r
12984 }\r
12985 // build system or some such environment...\r
12986 var last = 0,\r
12987 // This method is called to notify the user of the current error status.\r
12988 notify = function() {\r
12989 var cnt = Ext.log && Ext.log.counters,\r
12990 n = cnt && (cnt.error + cnt.warn + cnt.info + cnt.log),\r
12991 msg;\r
12992 // Put log counters to the status bar (for most browsers):\r
12993 if (n && last !== n) {\r
12994 msg = [];\r
12995 if (cnt.error) {\r
12996 msg.push('Errors: ' + cnt.error);\r
12997 }\r
12998 if (cnt.warn) {\r
12999 msg.push('Warnings: ' + cnt.warn);\r
13000 }\r
13001 if (cnt.info) {\r
13002 msg.push('Info: ' + cnt.info);\r
13003 }\r
13004 if (cnt.log) {\r
13005 msg.push('Log: ' + cnt.log);\r
13006 }\r
13007 window.status = '*** ' + msg.join(' -- ');\r
13008 last = n;\r
13009 }\r
13010 };\r
13011 // window.onerror sounds ideal but it prevents the built-in error dialog from doing\r
13012 // its (better) thing.\r
13013 setInterval(notify, 1000);\r
13014}());\r
13015\r
13016/**
13017 * @class Ext.Array
13018 * @singleton
13019 *
13020 * A set of useful static methods to deal with arrays; provide missing methods for
13021 * older browsers.
13022 */\r
13023Ext.Array = (function() {\r
13024 // @define Ext.lang.Array\r
13025 // @define Ext.Array\r
13026 // @require Ext\r
13027 // @require Ext.lang.Error\r
13028 var arrayPrototype = Array.prototype,\r
13029 slice = arrayPrototype.slice,\r
13030 supportsSplice = (function() {\r
13031 var array = [],\r
13032 lengthBefore,\r
13033 j = 20;\r
13034 if (!array.splice) {\r
13035 return false;\r
13036 }\r
13037 // This detects a bug in IE8 splice method:\r
13038 // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/\r
13039 while (j--) {\r
13040 array.push("A");\r
13041 }\r
13042 array.splice(15, 0, "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", "F");\r
13043 lengthBefore = array.length;\r
13044 //41\r
13045 array.splice(13, 0, "XXX");\r
13046 // add one element\r
13047 if (lengthBefore + 1 !== array.length) {\r
13048 return false;\r
13049 }\r
13050 // end IE8 bug\r
13051 return true;\r
13052 }()),\r
13053 supportsIndexOf = 'indexOf' in arrayPrototype,\r
13054 supportsSliceOnNodeList = true;\r
13055 // Sort an array using the comparator, but if the comparator returns zero, use the objects' original indices to tiebreak\r
13056 // This results in a stable sort.\r
13057 function stableSort(array, userComparator) {\r
13058 var len = array.length,\r
13059 indices = new Array(len),\r
13060 i;\r
13061 // generate 0-n index map from original array\r
13062 for (i = 0; i < len; i++) {\r
13063 indices[i] = i;\r
13064 }\r
13065 // Sort indices array using a comparator which compares the original values at the two indices, and uses those indices as a tiebreaker\r
13066 indices.sort(function(index1, index2) {\r
13067 return userComparator(array[index1], array[index2]) || (index1 - index2);\r
13068 });\r
13069 // Reconsitute a sorted array using the array that the indices have been sorted into\r
13070 for (i = 0; i < len; i++) {\r
13071 indices[i] = array[indices[i]];\r
13072 }\r
13073 // Rebuild the original array\r
13074 for (i = 0; i < len; i++) {\r
13075 array[i] = indices[i];\r
13076 }\r
13077 return array;\r
13078 }\r
13079 try {\r
13080 // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList\r
13081 if (typeof document !== 'undefined') {\r
13082 slice.call(document.getElementsByTagName('body'));\r
13083 }\r
13084 } catch (e) {\r
13085 supportsSliceOnNodeList = false;\r
13086 }\r
13087 var fixArrayIndex = function(array, index) {\r
13088 return (index < 0) ? Math.max(0, array.length + index) : Math.min(array.length, index);\r
13089 },\r
13090 /*
13091 Does the same work as splice, but with a slightly more convenient signature. The splice
13092 method has bugs in IE8, so this is the implementation we use on that platform.
13093
13094 The rippling of items in the array can be tricky. Consider two use cases:
13095
13096 index=2
13097 removeCount=2
13098 /=====\
13099 +---+---+---+---+---+---+---+---+
13100 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
13101 +---+---+---+---+---+---+---+---+
13102 / \/ \/ \/ \
13103 / /\ /\ /\ \
13104 / / \/ \/ \ +--------------------------+
13105 / / /\ /\ +--------------------------+ \
13106 / / / \/ +--------------------------+ \ \
13107 / / / /+--------------------------+ \ \ \
13108 / / / / \ \ \ \
13109 v v v v v v v v
13110 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
13111 | 0 | 1 | 4 | 5 | 6 | 7 | | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
13112 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
13113 A B \=========/
13114 insert=[a,b,c]
13115
13116 In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
13117 that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
13118 must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
13119 */\r
13120 replaceSim = function(array, index, removeCount, insert) {\r
13121 var add = insert ? insert.length : 0,\r
13122 length = array.length,\r
13123 pos = fixArrayIndex(array, index);\r
13124 // we try to use Array.push when we can for efficiency...\r
13125 if (pos === length) {\r
13126 if (add) {\r
13127 array.push.apply(array, insert);\r
13128 }\r
13129 } else {\r
13130 var remove = Math.min(removeCount, length - pos),\r
13131 tailOldPos = pos + remove,\r
13132 tailNewPos = tailOldPos + add - remove,\r
13133 tailCount = length - tailOldPos,\r
13134 lengthAfterRemove = length - remove,\r
13135 i;\r
13136 if (tailNewPos < tailOldPos) {\r
13137 // case A\r
13138 for (i = 0; i < tailCount; ++i) {\r
13139 array[tailNewPos + i] = array[tailOldPos + i];\r
13140 }\r
13141 } else if (tailNewPos > tailOldPos) {\r
13142 // case B\r
13143 for (i = tailCount; i--; ) {\r
13144 array[tailNewPos + i] = array[tailOldPos + i];\r
13145 }\r
13146 }\r
13147 // else, add == remove (nothing to do)\r
13148 if (add && pos === lengthAfterRemove) {\r
13149 array.length = lengthAfterRemove;\r
13150 // truncate array\r
13151 array.push.apply(array, insert);\r
13152 } else {\r
13153 array.length = lengthAfterRemove + add;\r
13154 // reserves space\r
13155 for (i = 0; i < add; ++i) {\r
13156 array[pos + i] = insert[i];\r
13157 }\r
13158 }\r
13159 }\r
13160 return array;\r
13161 },\r
13162 replaceNative = function(array, index, removeCount, insert) {\r
13163 if (insert && insert.length) {\r
13164 // Inserting at index zero with no removing: use unshift\r
13165 if (index === 0 && !removeCount) {\r
13166 array.unshift.apply(array, insert);\r
13167 }\r
13168 // Inserting/replacing in middle of array\r
13169 else if (index < array.length) {\r
13170 array.splice.apply(array, [\r
13171 index,\r
13172 removeCount\r
13173 ].concat(insert));\r
13174 } else // Appending to array\r
13175 {\r
13176 array.push.apply(array, insert);\r
13177 }\r
13178 } else {\r
13179 array.splice(index, removeCount);\r
13180 }\r
13181 return array;\r
13182 },\r
13183 eraseSim = function(array, index, removeCount) {\r
13184 return replaceSim(array, index, removeCount);\r
13185 },\r
13186 eraseNative = function(array, index, removeCount) {\r
13187 array.splice(index, removeCount);\r
13188 return array;\r
13189 },\r
13190 spliceSim = function(array, index, removeCount) {\r
13191 var pos = fixArrayIndex(array, index),\r
13192 removed = array.slice(index, fixArrayIndex(array, pos + removeCount));\r
13193 if (arguments.length < 4) {\r
13194 replaceSim(array, pos, removeCount);\r
13195 } else {\r
13196 replaceSim(array, pos, removeCount, slice.call(arguments, 3));\r
13197 }\r
13198 return removed;\r
13199 },\r
13200 spliceNative = function(array) {\r
13201 return array.splice.apply(array, slice.call(arguments, 1));\r
13202 },\r
13203 erase = supportsSplice ? eraseNative : eraseSim,\r
13204 replace = supportsSplice ? replaceNative : replaceSim,\r
13205 splice = supportsSplice ? spliceNative : spliceSim,\r
13206 // NOTE: from here on, use erase, replace or splice (not native methods)...\r
13207 ExtArray = {\r
13208 /**
13209 * This method returns the index that a given item would be inserted into the
13210 * given (sorted) `array`. Note that the given `item` may or may not be in the
13211 * array. This method will return the index of where the item *should* be.
13212 *
13213 * For example:
13214 *
13215 * var array = [ 'A', 'D', 'G', 'K', 'O', 'R', 'X' ];
13216 * var index = Ext.Array.binarySearch(array, 'E');
13217 *
13218 * console.log('index: ' + index);
13219 * // logs "index: 2"
13220 *
13221 * array.splice(index, 0, 'E');
13222 *
13223 * console.log('array : ' + array.join(''));
13224 * // logs "array: ADEGKORX"
13225 *
13226 * @param {Object[]} array The array to search.
13227 * @param {Object} item The item that you want to insert into the `array`.
13228 * @param {Number} [begin=0] The first index in the `array` to consider.
13229 * @param {Number} [end=array.length] The index that marks the end of the range
13230 * to consider. The item at this index is *not* considered.
13231 * @param {Function} [compareFn] The comparison function that matches the sort
13232 * order of the `array`. The default `compareFn` compares items using less-than
13233 * and greater-than operators.
13234 * @return {Number} The index for the given item in the given array based on
13235 * the current sorters.
13236 */\r
13237 binarySearch: function(array, item, begin, end, compareFn) {\r
13238 var length = array.length,\r
13239 middle, comparison;\r
13240 if (begin instanceof Function) {\r
13241 compareFn = begin;\r
13242 begin = 0;\r
13243 end = length;\r
13244 } else if (end instanceof Function) {\r
13245 compareFn = end;\r
13246 end = length;\r
13247 } else {\r
13248 if (begin === undefined) {\r
13249 begin = 0;\r
13250 }\r
13251 if (end === undefined) {\r
13252 end = length;\r
13253 }\r
13254 compareFn = compareFn || ExtArray.lexicalCompare;\r
13255 }\r
13256 --end;\r
13257 while (begin <= end) {\r
13258 middle = (begin + end) >> 1;\r
13259 comparison = compareFn(item, array[middle]);\r
13260 if (comparison >= 0) {\r
13261 begin = middle + 1;\r
13262 } else if (comparison < 0) {\r
13263 end = middle - 1;\r
13264 }\r
13265 }\r
13266 return begin;\r
13267 },\r
13268 defaultCompare: function(lhs, rhs) {\r
13269 return (lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0);\r
13270 },\r
13271 // Default comparator to use when no comparator is specified for the sort method.\r
13272 // Javascript sort does LEXICAL comparison.\r
13273 lexicalCompare: function(lhs, rhs) {\r
13274 lhs = String(lhs);\r
13275 rhs = String(rhs);\r
13276 return (lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0);\r
13277 },\r
13278 /**
13279 * Iterates an array or an iterable value and invoke the given callback function for each item.
13280 *
13281 * var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
13282 *
13283 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
13284 * console.log(name);
13285 * });
13286 *
13287 * var sum = function() {
13288 * var sum = 0;
13289 *
13290 * Ext.Array.each(arguments, function(value) {
13291 * sum += value;
13292 * });
13293 *
13294 * return sum;
13295 * };
13296 *
13297 * sum(1, 2, 3); // returns 6
13298 *
13299 * The iteration can be stopped by returning `false` from the callback function.
13300 * Returning `undefined` (i.e `return;`) will only exit the callback function and
13301 * proceed with the next iteration of the loop.
13302 *
13303 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
13304 * if (name === 'Singapore') {
13305 * return false; // break here
13306 * }
13307 * });
13308 *
13309 * {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
13310 *
13311 * @param {Array/NodeList/Object} iterable The value to be iterated. If this
13312 * argument is not iterable, the callback function is called once.
13313 * @param {Function} fn The callback function. If it returns `false`, the iteration
13314 * stops and this method returns the current `index`. Returning `undefined` (i.e
13315 * `return;`) will only exit the callback function and proceed with the next iteration
13316 * in the loop.
13317 * @param {Object} fn.item The item at the current `index` in the passed `array`
13318 * @param {Number} fn.index The current `index` within the `array`
13319 * @param {Array} fn.allItems The `array` itself which was passed as the first argument
13320 * @param {Boolean} fn.return Return `false` to stop iteration.
13321 * @param {Object} [scope] The scope (`this` reference) in which the specified function is executed.
13322 * @param {Boolean} [reverse=false] Reverse the iteration order (loop from the end to the beginning).
13323 * @return {Boolean} See description for the `fn` parameter.
13324 */\r
13325 each: function(array, fn, scope, reverse) {\r
13326 array = ExtArray.from(array);\r
13327 var i,\r
13328 ln = array.length;\r
13329 if (reverse !== true) {\r
13330 for (i = 0; i < ln; i++) {\r
13331 if (fn.call(scope || array[i], array[i], i, array) === false) {\r
13332 return i;\r
13333 }\r
13334 }\r
13335 } else {\r
13336 for (i = ln - 1; i > -1; i--) {\r
13337 if (fn.call(scope || array[i], array[i], i, array) === false) {\r
13338 return i;\r
13339 }\r
13340 }\r
13341 }\r
13342 return true;\r
13343 },\r
13344 /**
13345 * @method
13346 * Iterates an array and invoke the given callback function for each item. Note that this will simply
13347 * delegate to the native `Array.prototype.forEach` method if supported. It doesn't support stopping the
13348 * iteration by returning `false` in the callback function like {@link Ext.Array#each}. However, performance
13349 * could be much better in modern browsers comparing with {@link Ext.Array#each}
13350 *
13351 * @param {Array} array The array to iterate.
13352 * @param {Function} fn The callback function.
13353 * @param {Object} fn.item The item at the current `index` in the passed `array`.
13354 * @param {Number} fn.index The current `index` within the `array`.
13355 * @param {Array} fn.allItems The `array` itself which was passed as the first argument.
13356 * @param {Object} scope (Optional) The execution scope (`this`) in which the
13357 * specified function is executed.
13358 */\r
13359 forEach: ('forEach' in arrayPrototype) ? function(array, fn, scope) {\r
13360 return array.forEach(fn, scope);\r
13361 } : function(array, fn, scope) {\r
13362 for (var i = 0,\r
13363 ln = array.length; i < ln; i++) {\r
13364 fn.call(scope, array[i], i, array);\r
13365 }\r
13366 },\r
13367 /**
13368 * @method
13369 * Get the index of the provided `item` in the given `array`, a supplement for the
13370 * missing arrayPrototype.indexOf in Internet Explorer.
13371 *
13372 * @param {Array} array The array to check.
13373 * @param {Object} item The item to find.
13374 * @param {Number} from (Optional) The index at which to begin the search.
13375 * @return {Number} The index of item in the array (or -1 if it is not found).
13376 */\r
13377 indexOf: supportsIndexOf ? function(array, item, from) {\r
13378 return arrayPrototype.indexOf.call(array, item, from);\r
13379 } : function(array, item, from) {\r
13380 var i,\r
13381 length = array.length;\r
13382 for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {\r
13383 if (array[i] === item) {\r
13384 return i;\r
13385 }\r
13386 }\r
13387 return -1;\r
13388 },\r
13389 /**
13390 * @method
13391 * Checks whether or not the given `array` contains the specified `item`.
13392 *
13393 * @param {Array} array The array to check.
13394 * @param {Object} item The item to find.
13395 * @return {Boolean} `true` if the array contains the item, `false` otherwise.
13396 */\r
13397 contains: supportsIndexOf ? function(array, item) {\r
13398 return arrayPrototype.indexOf.call(array, item) !== -1;\r
13399 } : function(array, item) {\r
13400 var i, ln;\r
13401 for (i = 0 , ln = array.length; i < ln; i++) {\r
13402 if (array[i] === item) {\r
13403 return true;\r
13404 }\r
13405 }\r
13406 return false;\r
13407 },\r
13408 /**
13409 * Converts any iterable (numeric indices and a length property) into a true array.
13410 *
13411 * function test() {
13412 * var args = Ext.Array.toArray(arguments),
13413 * fromSecondToLastArgs = Ext.Array.toArray(arguments, 1);
13414 *
13415 * alert(args.join(' '));
13416 * alert(fromSecondToLastArgs.join(' '));
13417 * }
13418 *
13419 * test('just', 'testing', 'here'); // alerts 'just testing here';
13420 * // alerts 'testing here';
13421 *
13422 * Ext.Array.toArray(document.getElementsByTagName('div')); // will convert the NodeList into an array
13423 * Ext.Array.toArray('splitted'); // returns ['s', 'p', 'l', 'i', 't', 't', 'e', 'd']
13424 * Ext.Array.toArray('splitted', 0, 3); // returns ['s', 'p', 'l']
13425 *
13426 * {@link Ext#toArray Ext.toArray} is alias for {@link Ext.Array#toArray Ext.Array.toArray}
13427 *
13428 * @param {Object} iterable the iterable object to be turned into a true Array.
13429 * @param {Number} [start=0] a zero-based index that specifies the start of extraction.
13430 * @param {Number} [end=-1] a 1-based index that specifies the end of extraction.
13431 * @return {Array}
13432 */\r
13433 toArray: function(iterable, start, end) {\r
13434 if (!iterable || !iterable.length) {\r
13435 return [];\r
13436 }\r
13437 if (typeof iterable === 'string') {\r
13438 iterable = iterable.split('');\r
13439 }\r
13440 if (supportsSliceOnNodeList) {\r
13441 return slice.call(iterable, start || 0, end || iterable.length);\r
13442 }\r
13443 var array = [],\r
13444 i;\r
13445 start = start || 0;\r
13446 end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;\r
13447 for (i = start; i < end; i++) {\r
13448 array.push(iterable[i]);\r
13449 }\r
13450 return array;\r
13451 },\r
13452 /**
13453 * Plucks the value of a property from each item in the Array. Example:
13454 *
13455 * Ext.Array.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
13456 *
13457 * @param {Array/NodeList} array The Array of items to pluck the value from.
13458 * @param {String} propertyName The property name to pluck from each element.
13459 * @return {Array} The value from each item in the Array.
13460 */\r
13461 pluck: function(array, propertyName) {\r
13462 var ret = [],\r
13463 i, ln, item;\r
13464 for (i = 0 , ln = array.length; i < ln; i++) {\r
13465 item = array[i];\r
13466 ret.push(item[propertyName]);\r
13467 }\r
13468 return ret;\r
13469 },\r
13470 /**
13471 * @method
13472 * Creates a new array with the results of calling a provided function on every element in this array.
13473 *
13474 * @param {Array} array
13475 * @param {Function} fn Callback function for each item.
13476 * @param {Mixed} fn.item Current item.
13477 * @param {Number} fn.index Index of the item.
13478 * @param {Array} fn.array The whole array that's being iterated.
13479 * @param {Object} [scope] Callback function scope
13480 * @return {Array} results
13481 */\r
13482 map: ('map' in arrayPrototype) ? function(array, fn, scope) {\r
13483 Ext.Assert.isFunction(fn, 'Ext.Array.map must have a callback function passed as second argument.');\r
13484 return array.map(fn, scope);\r
13485 } : function(array, fn, scope) {\r
13486 Ext.Assert.isFunction(fn, 'Ext.Array.map must have a callback function passed as second argument.');\r
13487 var results = [],\r
13488 len = array.length,\r
13489 i;\r
13490 for (i = 0; i < len; i++) {\r
13491 results[i] = fn.call(scope, array[i], i, array);\r
13492 }\r
13493 return results;\r
13494 },\r
13495 /**
13496 * @method
13497 * Executes the specified function for each array element until the function returns a falsy value.
13498 * If such an item is found, the function will return `false` immediately.
13499 * Otherwise, it will return `true`.
13500 *
13501 * @param {Array} array
13502 * @param {Function} fn Callback function for each item.
13503 * @param {Mixed} fn.item Current item.
13504 * @param {Number} fn.index Index of the item.
13505 * @param {Array} fn.array The whole array that's being iterated.
13506 * @param {Object} scope Callback function scope.
13507 * @return {Boolean} `treu` if no false value is returned by the callback function.
13508 */\r
13509 every: ('every' in arrayPrototype) ? function(array, fn, scope) {\r
13510 Ext.Assert.isFunction(fn, 'Ext.Array.every must have a callback function passed as second argument.');\r
13511 return array.every(fn, scope);\r
13512 } : function(array, fn, scope) {\r
13513 Ext.Assert.isFunction(fn, 'Ext.Array.every must have a callback function passed as second argument.');\r
13514 var i = 0,\r
13515 ln = array.length;\r
13516 for (; i < ln; ++i) {\r
13517 if (!fn.call(scope, array[i], i, array)) {\r
13518 return false;\r
13519 }\r
13520 }\r
13521 return true;\r
13522 },\r
13523 /**
13524 * @method
13525 * Executes the specified function for each array element until the function returns a truthy value.
13526 * If such an item is found, the function will return `true` immediately. Otherwise, it will return `false`.
13527 *
13528 * @param {Array} array
13529 * @param {Function} fn Callback function for each item.
13530 * @param {Mixed} fn.item Current item.
13531 * @param {Number} fn.index Index of the item.
13532 * @param {Array} fn.array The whole array that's being iterated.
13533 * @param {Object} scope Callback function scope.
13534 * @return {Boolean} `true` if the callback function returns a truthy value.
13535 */\r
13536 some: ('some' in arrayPrototype) ? function(array, fn, scope) {\r
13537 Ext.Assert.isFunction(fn, 'Ext.Array.some must have a callback function passed as second argument.');\r
13538 return array.some(fn, scope);\r
13539 } : function(array, fn, scope) {\r
13540 Ext.Assert.isFunction(fn, 'Ext.Array.some must have a callback function passed as second argument.');\r
13541 var i = 0,\r
13542 ln = array.length;\r
13543 for (; i < ln; ++i) {\r
13544 if (fn.call(scope, array[i], i, array)) {\r
13545 return true;\r
13546 }\r
13547 }\r
13548 return false;\r
13549 },\r
13550 /**
13551 * Shallow compares the contents of 2 arrays using strict equality.
13552 * @param {Array} array1
13553 * @param {Array} array2
13554 * @return {Boolean} `true` if the arrays are equal.
13555 */\r
13556 equals: function(array1, array2) {\r
13557 var len1 = array1.length,\r
13558 len2 = array2.length,\r
13559 i;\r
13560 // Short circuit if the same array is passed twice\r
13561 if (array1 === array2) {\r
13562 return true;\r
13563 }\r
13564 if (len1 !== len2) {\r
13565 return false;\r
13566 }\r
13567 for (i = 0; i < len1; ++i) {\r
13568 if (array1[i] !== array2[i]) {\r
13569 return false;\r
13570 }\r
13571 }\r
13572 return true;\r
13573 },\r
13574 /**
13575 * Filter through an array and remove empty item as defined in {@link Ext#isEmpty Ext.isEmpty}.
13576 *
13577 * See {@link Ext.Array#filter}
13578 *
13579 * @param {Array} array
13580 * @return {Array} results
13581 */\r
13582 clean: function(array) {\r
13583 var results = [],\r
13584 i = 0,\r
13585 ln = array.length,\r
13586 item;\r
13587 for (; i < ln; i++) {\r
13588 item = array[i];\r
13589 if (!Ext.isEmpty(item)) {\r
13590 results.push(item);\r
13591 }\r
13592 }\r
13593 return results;\r
13594 },\r
13595 /**
13596 * Returns a new array with unique items.
13597 *
13598 * @param {Array} array
13599 * @return {Array} results
13600 */\r
13601 unique: function(array) {\r
13602 var clone = [],\r
13603 i = 0,\r
13604 ln = array.length,\r
13605 item;\r
13606 for (; i < ln; i++) {\r
13607 item = array[i];\r
13608 if (ExtArray.indexOf(clone, item) === -1) {\r
13609 clone.push(item);\r
13610 }\r
13611 }\r
13612 return clone;\r
13613 },\r
13614 /**
13615 * @method
13616 * Creates a new array with all of the elements of this array for which
13617 * the provided filtering function returns a truthy value.
13618 *
13619 * @param {Array} array
13620 * @param {Function} fn Callback function for each item.
13621 * @param {Mixed} fn.item Current item.
13622 * @param {Number} fn.index Index of the item.
13623 * @param {Array} fn.array The whole array that's being iterated.
13624 * @param {Object} scope Callback function scope.
13625 * @return {Array} results
13626 */\r
13627 filter: ('filter' in arrayPrototype) ? function(array, fn, scope) {\r
13628 Ext.Assert.isFunction(fn, 'Ext.Array.filter must have a filter function passed as second argument.');\r
13629 return array.filter(fn, scope);\r
13630 } : function(array, fn, scope) {\r
13631 Ext.Assert.isFunction(fn, 'Ext.Array.filter must have a filter function passed as second argument.');\r
13632 var results = [],\r
13633 i = 0,\r
13634 ln = array.length;\r
13635 for (; i < ln; i++) {\r
13636 if (fn.call(scope, array[i], i, array)) {\r
13637 results.push(array[i]);\r
13638 }\r
13639 }\r
13640 return results;\r
13641 },\r
13642 /**
13643 * Returns the first item in the array which elicits a truthy return value from the
13644 * passed selection function.
13645 * @param {Array} array The array to search
13646 * @param {Function} fn The selection function to execute for each item.
13647 * @param {Mixed} fn.item The array item.
13648 * @param {String} fn.index The index of the array item.
13649 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the
13650 * function is executed. Defaults to the array
13651 * @return {Object} The first item in the array which returned true from the selection
13652 * function, or null if none was found.
13653 */\r
13654 findBy: function(array, fn, scope) {\r
13655 var i = 0,\r
13656 len = array.length;\r
13657 for (; i < len; i++) {\r
13658 if (fn.call(scope || array, array[i], i)) {\r
13659 return array[i];\r
13660 }\r
13661 }\r
13662 return null;\r
13663 },\r
13664 /**
13665 * Converts a value to an array if it's not already an array; returns:
13666 *
13667 * - An empty array if given value is `undefined` or `null`
13668 * - Itself if given value is already an array
13669 * - An array copy if given value is {@link Ext#isIterable iterable} (arguments, NodeList and alike)
13670 * - An array with one item which is the given value, otherwise
13671 *
13672 * @param {Object} value The value to convert to an array if it's not already is an array.
13673 * @param {Boolean} [newReference] `true` to clone the given array and return a new reference if necessary.
13674 * @return {Array} array
13675 */\r
13676 from: function(value, newReference) {\r
13677 if (value === undefined || value === null) {\r
13678 return [];\r
13679 }\r
13680 if (Ext.isArray(value)) {\r
13681 return (newReference) ? slice.call(value) : value;\r
13682 }\r
13683 var type = typeof value;\r
13684 // Both strings and functions will have a length property. In phantomJS, NodeList\r
13685 // instances report typeof=='function' but don't have an apply method...\r
13686 if (value && value.length !== undefined && type !== 'string' && (type !== 'function' || !value.apply)) {\r
13687 return ExtArray.toArray(value);\r
13688 }\r
13689 return [\r
13690 value\r
13691 ];\r
13692 },\r
13693 /**
13694 * Removes the specified item from the array if it exists.
13695 *
13696 * @param {Array} array The array.
13697 * @param {Object} item The item to remove.
13698 * @return {Array} The passed array.
13699 */\r
13700 remove: function(array, item) {\r
13701 var index = ExtArray.indexOf(array, item);\r
13702 if (index !== -1) {\r
13703 erase(array, index, 1);\r
13704 }\r
13705 return array;\r
13706 },\r
13707 /**
13708 * Removes item/s at the specified index.
13709 *
13710 * @param {Array} array The array.
13711 * @param {Number} index The index of the item to be removed.
13712 * @param {Number} [count=1] The number of items to be removed.
13713 * @return {Array} The passed array.
13714 */\r
13715 removeAt: function(array, index, count) {\r
13716 var len = array.length;\r
13717 if (index >= 0 && index < len) {\r
13718 count = count || 1;\r
13719 count = Math.min(count, len - index);\r
13720 erase(array, index, count);\r
13721 }\r
13722 return array;\r
13723 },\r
13724 /**
13725 * Push an item into the array only if the array doesn't contain it yet.
13726 *
13727 * @param {Array} array The array.
13728 * @param {Object} item The item to include.
13729 */\r
13730 include: function(array, item) {\r
13731 if (!ExtArray.contains(array, item)) {\r
13732 array.push(item);\r
13733 }\r
13734 },\r
13735 /**
13736 * Clone a flat array without referencing the previous one. Note that this is different
13737 * from `Ext.clone` since it doesn't handle recursive cloning. It's simply a convenient, easy-to-remember method
13738 * for `Array.prototype.slice.call(array)`.
13739 *
13740 * @param {Array} array The array.
13741 * @return {Array} The clone array.
13742 */\r
13743 clone: function(array) {\r
13744 return slice.call(array);\r
13745 },\r
13746 /**
13747 * Merge multiple arrays into one with unique items.
13748 *
13749 * {@link Ext.Array#union} is alias for {@link Ext.Array#merge}
13750 *
13751 * @param {Array} array1
13752 * @param {Array} array2
13753 * @param {Array} etc
13754 * @return {Array} merged
13755 */\r
13756 merge: function() {\r
13757 var args = slice.call(arguments),\r
13758 array = [],\r
13759 i, ln;\r
13760 for (i = 0 , ln = args.length; i < ln; i++) {\r
13761 array = array.concat(args[i]);\r
13762 }\r
13763 return ExtArray.unique(array);\r
13764 },\r
13765 /**
13766 * Merge multiple arrays into one with unique items that exist in all of the arrays.
13767 *
13768 * @param {Array} array1
13769 * @param {Array} array2
13770 * @param {Array} etc
13771 * @return {Array} intersect
13772 */\r
13773 intersect: function() {\r
13774 var intersection = [],\r
13775 arrays = slice.call(arguments),\r
13776 arraysLength, array, arrayLength, minArray, minArrayIndex, minArrayCandidate, minArrayLength, element, elementCandidate, elementCount, i, j, k;\r
13777 if (!arrays.length) {\r
13778 return intersection;\r
13779 }\r
13780 // Find the smallest array\r
13781 arraysLength = arrays.length;\r
13782 for (i = minArrayIndex = 0; i < arraysLength; i++) {\r
13783 minArrayCandidate = arrays[i];\r
13784 if (!minArray || minArrayCandidate.length < minArray.length) {\r
13785 minArray = minArrayCandidate;\r
13786 minArrayIndex = i;\r
13787 }\r
13788 }\r
13789 minArray = ExtArray.unique(minArray);\r
13790 erase(arrays, minArrayIndex, 1);\r
13791 // Use the smallest unique'd array as the anchor loop. If the other array(s) do contain\r
13792 // an item in the small array, we're likely to find it before reaching the end\r
13793 // of the inner loop and can terminate the search early.\r
13794 minArrayLength = minArray.length;\r
13795 arraysLength = arrays.length;\r
13796 for (i = 0; i < minArrayLength; i++) {\r
13797 element = minArray[i];\r
13798 elementCount = 0;\r
13799 for (j = 0; j < arraysLength; j++) {\r
13800 array = arrays[j];\r
13801 arrayLength = array.length;\r
13802 for (k = 0; k < arrayLength; k++) {\r
13803 elementCandidate = array[k];\r
13804 if (element === elementCandidate) {\r
13805 elementCount++;\r
13806 break;\r
13807 }\r
13808 }\r
13809 }\r
13810 if (elementCount === arraysLength) {\r
13811 intersection.push(element);\r
13812 }\r
13813 }\r
13814 return intersection;\r
13815 },\r
13816 /**
13817 * Perform a set difference A-B by subtracting all items in array B from array A.
13818 *
13819 * @param {Array} arrayA
13820 * @param {Array} arrayB
13821 * @return {Array} difference
13822 */\r
13823 difference: function(arrayA, arrayB) {\r
13824 var clone = slice.call(arrayA),\r
13825 ln = clone.length,\r
13826 i, j, lnB;\r
13827 for (i = 0 , lnB = arrayB.length; i < lnB; i++) {\r
13828 for (j = 0; j < ln; j++) {\r
13829 if (clone[j] === arrayB[i]) {\r
13830 erase(clone, j, 1);\r
13831 j--;\r
13832 ln--;\r
13833 }\r
13834 }\r
13835 }\r
13836 return clone;\r
13837 },\r
13838 /**
13839 * This method applies the `reduceFn` function against an accumulator and each
13840 * value of the `array` (from left-to-right) to reduce it to a single value.
13841 *
13842 * If no `initialValue` is specified, the first element of the array is used as
13843 * the initial value. For example:
13844 *
13845 * function reducer (previous, value, index) {
13846 * console.log('[' + index + ']: (' + previous + ',' + value + '}');
13847 * return previous * 10 + value;
13848 * }
13849 *
13850 * v = Ext.Array.reduce([2, 3, 4], reducer);
13851 * console.log('v = ' + v);
13852 *
13853 * > [1]: (2, 3)
13854 * > [2]: (23, 4)
13855 * > v = 234
13856 *
13857 * v = Ext.Array.reduce([2, 3, 4], reducer, 1);
13858 * console.log('v = ' + v);
13859 *
13860 * > [0]: (1, 2)
13861 * > [1]: (12, 3)
13862 * > [2]: (123, 4)
13863 * > v = 1234
13864 *
13865 * @param {Array} array The array to process.
13866 * @param {Function} reduceFn The reducing callback function.
13867 * @param {Mixed} reduceFn.previous The previous value.
13868 * @param {Mixed} reduceFn.value The current value.
13869 * @param {Number} reduceFn.index The index in the array of the current `value`.
13870 * @param {Array} reduceFn.array The array to being processed.
13871 * @param {Mixed} [initialValue] The starting value.
13872 * @return {Mixed} The reduced value.
13873 * @method reduce
13874 * @since 6.0.0
13875 */\r
13876 reduce: Array.prototype.reduce ? function(array, reduceFn, initialValue) {\r
13877 if (arguments.length === 3) {\r
13878 return Array.prototype.reduce.call(array, reduceFn, initialValue);\r
13879 }\r
13880 return Array.prototype.reduce.call(array, reduceFn);\r
13881 } : function(array, reduceFn, initialValue) {\r
13882 array = Object(array);\r
13883 if (!Ext.isFunction(reduceFn)) {\r
13884 Ext.raise('Invalid parameter: expected a function.');\r
13885 }\r
13886 var index = 0,\r
13887 length = array.length >>> 0,\r
13888 reduced = initialValue;\r
13889 if (arguments.length < 3) {\r
13890 while (true) {\r
13891 if (index in array) {\r
13892 reduced = array[index++];\r
13893 break;\r
13894 }\r
13895 if (++index >= length) {\r
13896 throw new TypeError('Reduce of empty array with no initial value');\r
13897 }\r
13898 }\r
13899 }\r
13900 for (; index < length; ++index) {\r
13901 if (index in array) {\r
13902 reduced = reduceFn(reduced, array[index], index, array);\r
13903 }\r
13904 }\r
13905 return reduced;\r
13906 },\r
13907 /**
13908 * Returns a shallow copy of a part of an array. This is equivalent to the native
13909 * call `Array.prototype.slice.call(array, begin, end)`. This is often used when "array"
13910 * is "arguments" since the arguments object does not supply a slice method but can
13911 * be the context object to `Array.prototype.slice`.
13912 *
13913 * @param {Array} array The array (or arguments object).
13914 * @param {Number} begin The index at which to begin. Negative values are offsets from
13915 * the end of the array.
13916 * @param {Number} end The index at which to end. The copied items do not include
13917 * end. Negative values are offsets from the end of the array. If end is omitted,
13918 * all items up to the end of the array are copied.
13919 * @return {Array} The copied piece of the array.
13920 * @method slice
13921 */\r
13922 // Note: IE8 will return [] on slice.call(x, undefined).\r
13923 slice: ([\r
13924 1,\r
13925 2\r
13926 ].slice(1, undefined).length ? function(array, begin, end) {\r
13927 return slice.call(array, begin, end);\r
13928 } : function(array, begin, end) {\r
13929 // see http://jsperf.com/slice-fix\r
13930 if (typeof begin === 'undefined') {\r
13931 return slice.call(array);\r
13932 }\r
13933 if (typeof end === 'undefined') {\r
13934 return slice.call(array, begin);\r
13935 }\r
13936 return slice.call(array, begin, end);\r
13937 }),\r
13938 /**
13939 * Sorts the elements of an Array in a stable manner (equivalently keyed values do not move relative to each other).
13940 * By default, this method sorts the elements alphabetically and ascending.
13941 * **Note:** This method modifies the passed array, in the same manner as the
13942 * native javascript Array.sort.
13943 *
13944 * @param {Array} array The array to sort.
13945 * @param {Function} [sortFn] The comparison function.
13946 * @param {Mixed} sortFn.a The first item to compare.
13947 * @param {Mixed} sortFn.b The second item to compare.
13948 * @param {Number} sortFn.return `-1` if a < b, `1` if a > b, otherwise `0`.
13949 * @return {Array} The sorted array.
13950 */\r
13951 sort: function(array, sortFn) {\r
13952 return stableSort(array, sortFn || ExtArray.lexicalCompare);\r
13953 },\r
13954 /**
13955 * Recursively flattens into 1-d Array. Injects Arrays inline.
13956 *
13957 * @param {Array} array The array to flatten
13958 * @return {Array} The 1-d array.
13959 */\r
13960 flatten: function(array) {\r
13961 var worker = [];\r
13962 function rFlatten(a) {\r
13963 var i, ln, v;\r
13964 for (i = 0 , ln = a.length; i < ln; i++) {\r
13965 v = a[i];\r
13966 if (Ext.isArray(v)) {\r
13967 rFlatten(v);\r
13968 } else {\r
13969 worker.push(v);\r
13970 }\r
13971 }\r
13972 return worker;\r
13973 }\r
13974 return rFlatten(array);\r
13975 },\r
13976 /**
13977 * Returns the minimum value in the Array.
13978 *
13979 * @param {Array/NodeList} array The Array from which to select the minimum value.
13980 * @param {Function} comparisonFn (optional) a function to perform the comparison which determines minimization.
13981 * If omitted the "<" operator will be used.
13982 * __Note:__ gt = 1; eq = 0; lt = -1
13983 * @param {Mixed} comparisonFn.min Current minimum value.
13984 * @param {Mixed} comparisonFn.item The value to compare with the current minimum.
13985 * @return {Object} minValue The minimum value.
13986 */\r
13987 min: function(array, comparisonFn) {\r
13988 var min = array[0],\r
13989 i, ln, item;\r
13990 for (i = 0 , ln = array.length; i < ln; i++) {\r
13991 item = array[i];\r
13992 if (comparisonFn) {\r
13993 if (comparisonFn(min, item) === 1) {\r
13994 min = item;\r
13995 }\r
13996 } else {\r
13997 if (item < min) {\r
13998 min = item;\r
13999 }\r
14000 }\r
14001 }\r
14002 return min;\r
14003 },\r
14004 /**
14005 * Returns the maximum value in the Array.
14006 *
14007 * @param {Array/NodeList} array The Array from which to select the maximum value.
14008 * @param {Function} comparisonFn (optional) a function to perform the comparison which determines maximization.
14009 * If omitted the ">" operator will be used.
14010 * __Note:__ gt = 1; eq = 0; lt = -1
14011 * @param {Mixed} comparisonFn.max Current maximum value.
14012 * @param {Mixed} comparisonFn.item The value to compare with the current maximum.
14013 * @return {Object} maxValue The maximum value.
14014 */\r
14015 max: function(array, comparisonFn) {\r
14016 var max = array[0],\r
14017 i, ln, item;\r
14018 for (i = 0 , ln = array.length; i < ln; i++) {\r
14019 item = array[i];\r
14020 if (comparisonFn) {\r
14021 if (comparisonFn(max, item) === -1) {\r
14022 max = item;\r
14023 }\r
14024 } else {\r
14025 if (item > max) {\r
14026 max = item;\r
14027 }\r
14028 }\r
14029 }\r
14030 return max;\r
14031 },\r
14032 /**
14033 * Calculates the mean of all items in the array.
14034 *
14035 * @param {Array} array The Array to calculate the mean value of.
14036 * @return {Number} The mean.
14037 */\r
14038 mean: function(array) {\r
14039 return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;\r
14040 },\r
14041 /**
14042 * Calculates the sum of all items in the given array.
14043 *
14044 * @param {Array} array The Array to calculate the sum value of.
14045 * @return {Number} The sum.
14046 */\r
14047 sum: function(array) {\r
14048 var sum = 0,\r
14049 i, ln, item;\r
14050 for (i = 0 , ln = array.length; i < ln; i++) {\r
14051 item = array[i];\r
14052 sum += item;\r
14053 }\r
14054 return sum;\r
14055 },\r
14056 /**
14057 * Creates a map (object) keyed by the elements of the given array. The values in
14058 * the map are the index+1 of the array element. For example:
14059 *
14060 * var map = Ext.Array.toMap(['a','b','c']);
14061 *
14062 * // map = { a: 1, b: 2, c: 3 };
14063 *
14064 * Or a key property can be specified:
14065 *
14066 * var map = Ext.Array.toMap([
14067 * { name: 'a' },
14068 * { name: 'b' },
14069 * { name: 'c' }
14070 * ], 'name');
14071 *
14072 * // map = { a: 1, b: 2, c: 3 };
14073 *
14074 * Lastly, a key extractor can be provided:
14075 *
14076 * var map = Ext.Array.toMap([
14077 * { name: 'a' },
14078 * { name: 'b' },
14079 * { name: 'c' }
14080 * ], function (obj) { return obj.name.toUpperCase(); });
14081 *
14082 * // map = { A: 1, B: 2, C: 3 };
14083 *
14084 * @param {Array} array The Array to create the map from.
14085 * @param {String/Function} [getKey] Name of the object property to use
14086 * as a key or a function to extract the key.
14087 * @param {Object} [scope] Value of `this` inside callback specified for `getKey`.
14088 * @return {Object} The resulting map.
14089 */\r
14090 toMap: function(array, getKey, scope) {\r
14091 var map = {},\r
14092 i = array.length;\r
14093 if (!getKey) {\r
14094 while (i--) {\r
14095 map[array[i]] = i + 1;\r
14096 }\r
14097 } else if (typeof getKey === 'string') {\r
14098 while (i--) {\r
14099 map[array[i][getKey]] = i + 1;\r
14100 }\r
14101 } else {\r
14102 while (i--) {\r
14103 map[getKey.call(scope, array[i])] = i + 1;\r
14104 }\r
14105 }\r
14106 return map;\r
14107 },\r
14108 /**
14109 * Creates a map (object) keyed by a property of elements of the given array. The values in
14110 * the map are the array element. For example:
14111 *
14112 * var map = Ext.Array.toValueMap(['a','b','c']);
14113 *
14114 * // map = { a: 'a', b: 'b', c: 'c' };
14115 *
14116 * Or a key property can be specified:
14117 *
14118 * var map = Ext.Array.toValueMap([
14119 * { name: 'a' },
14120 * { name: 'b' },
14121 * { name: 'c' }
14122 * ], 'name');
14123 *
14124 * // map = { a: {name: 'a'}, b: {name: 'b'}, c: {name: 'c'} };
14125 *
14126 * Lastly, a key extractor can be provided:
14127 *
14128 * var map = Ext.Array.toValueMap([
14129 * { name: 'a' },
14130 * { name: 'b' },
14131 * { name: 'c' }
14132 * ], function (obj) { return obj.name.toUpperCase(); });
14133 *
14134 * // map = { A: {name: 'a'}, B: {name: 'b'}, C: {name: 'c'} };
14135 *
14136 * @param {Array} array The Array to create the map from.
14137 * @param {String/Function} [getKey] Name of the object property to use
14138 * as a key or a function to extract the key.
14139 * @param {Object} [scope] Value of this inside callback. This parameter is only
14140 * passed when `getKey` is a function. If `getKey` is not a function, the 3rd
14141 * argument is `arrayify`.
14142 * @param {Number} [arrayify] Pass `1` to create arrays for all map entries
14143 * or `2` to create arrays for map entries that have 2 or more items with the
14144 * same key. This only applies when `getKey` is specified. By default the map will
14145 * hold the last entry with a given key.
14146 * @return {Object} The resulting map.
14147 */\r
14148 toValueMap: function(array, getKey, scope, arrayify) {\r
14149 var map = {},\r
14150 i = array.length,\r
14151 autoArray, alwaysArray, entry, fn, key, value;\r
14152 if (!getKey) {\r
14153 while (i--) {\r
14154 value = array[i];\r
14155 map[value] = value;\r
14156 }\r
14157 } else {\r
14158 if (!(fn = (typeof getKey !== 'string'))) {\r
14159 arrayify = scope;\r
14160 }\r
14161 alwaysArray = arrayify === 1;\r
14162 autoArray = arrayify === 2;\r
14163 while (i--) {\r
14164 value = array[i];\r
14165 key = fn ? getKey.call(scope, value) : value[getKey];\r
14166 if (alwaysArray) {\r
14167 if (key in map) {\r
14168 map[key].push(value);\r
14169 } else {\r
14170 map[key] = [\r
14171 value\r
14172 ];\r
14173 }\r
14174 } else if (autoArray && (key in map)) {\r
14175 if ((entry = map[key]) instanceof Array) {\r
14176 entry.push(value);\r
14177 } else {\r
14178 map[key] = [\r
14179 entry,\r
14180 value\r
14181 ];\r
14182 }\r
14183 } else {\r
14184 map[key] = value;\r
14185 }\r
14186 }\r
14187 }\r
14188 return map;\r
14189 },\r
14190 _replaceSim: replaceSim,\r
14191 // for unit testing\r
14192 _spliceSim: spliceSim,\r
14193 /**
14194 * Removes items from an array. This is functionally equivalent to the splice method
14195 * of Array, but works around bugs in IE8's splice method and does not copy the
14196 * removed elements in order to return them (because very often they are ignored).
14197 *
14198 * @param {Array} array The Array on which to replace.
14199 * @param {Number} index The index in the array at which to operate.
14200 * @param {Number} removeCount The number of items to remove at index.
14201 * @return {Array} The array passed.
14202 * @method
14203 */\r
14204 erase: erase,\r
14205 /**
14206 * Inserts items in to an array.
14207 *
14208 * @param {Array} array The Array in which to insert.
14209 * @param {Number} index The index in the array at which to operate.
14210 * @param {Array} items The array of items to insert at index.
14211 * @return {Array} The array passed.
14212 */\r
14213 insert: function(array, index, items) {\r
14214 return replace(array, index, 0, items);\r
14215 },\r
14216 move: function(array, fromIdx, toIdx) {\r
14217 if (toIdx === fromIdx) {\r
14218 return;\r
14219 }\r
14220 var item = array[fromIdx],\r
14221 incr = toIdx > fromIdx ? 1 : -1,\r
14222 i;\r
14223 for (i = fromIdx; i != toIdx; i += incr) {\r
14224 array[i] = array[i + incr];\r
14225 }\r
14226 array[toIdx] = item;\r
14227 },\r
14228 /**
14229 * Replaces items in an array. This is functionally equivalent to the splice method
14230 * of Array, but works around bugs in IE8's splice method and is often more convenient
14231 * to call because it accepts an array of items to insert rather than use a variadic
14232 * argument list.
14233 *
14234 * @param {Array} array The Array on which to replace.
14235 * @param {Number} index The index in the array at which to operate.
14236 * @param {Number} removeCount The number of items to remove at index (can be 0).
14237 * @param {Array} insert (optional) An array of items to insert at index.
14238 * @return {Array} The array passed.
14239 * @method
14240 */\r
14241 replace: replace,\r
14242 /**
14243 * Replaces items in an array. This is equivalent to the splice method of Array, but
14244 * works around bugs in IE8's splice method. The signature is exactly the same as the
14245 * splice method except that the array is the first argument. All arguments following
14246 * removeCount are inserted in the array at index.
14247 *
14248 * @param {Array} array The Array on which to replace.
14249 * @param {Number} index The index in the array at which to operate.
14250 * @param {Number} removeCount The number of items to remove at index (can be 0).
14251 * @param {Object...} elements The elements to add to the array. If you don't specify
14252 * any elements, splice simply removes elements from the array.
14253 * @return {Array} An array containing the removed items.
14254 * @method
14255 */\r
14256 splice: splice,\r
14257 /**
14258 * Pushes new items onto the end of an Array.
14259 *
14260 * Passed parameters may be single items, or arrays of items. If an Array is found in the argument list, all its
14261 * elements are pushed into the end of the target Array.
14262 *
14263 * @param {Array} target The Array onto which to push new items
14264 * @param {Object...} elements The elements to add to the array. Each parameter may
14265 * be an Array, in which case all the elements of that Array will be pushed into the end of the
14266 * destination Array.
14267 * @return {Array} An array containing all the new items push onto the end.
14268 *
14269 */\r
14270 push: function(target) {\r
14271 var len = arguments.length,\r
14272 i = 1,\r
14273 newItem;\r
14274 if (target === undefined) {\r
14275 target = [];\r
14276 } else if (!Ext.isArray(target)) {\r
14277 target = [\r
14278 target\r
14279 ];\r
14280 }\r
14281 for (; i < len; i++) {\r
14282 newItem = arguments[i];\r
14283 Array.prototype.push[Ext.isIterable(newItem) ? 'apply' : 'call'](target, newItem);\r
14284 }\r
14285 return target;\r
14286 },\r
14287 /**
14288 * A function used to sort an array by numeric value. By default, javascript array values
14289 * are coerced to strings when sorting, which can be problematic when using numeric values. To
14290 * ensure that the values are sorted numerically, this method can be passed to the sort method:
14291 *
14292 * Ext.Array.sort(myArray, Ext.Array.numericSortFn);
14293 */\r
14294 numericSortFn: function(a, b) {\r
14295 return a - b;\r
14296 }\r
14297 };\r
14298 /**
14299 * @method
14300 * @member Ext
14301 * @inheritdoc Ext.Array#each
14302 */\r
14303 Ext.each = ExtArray.each;\r
14304 /**
14305 * @method
14306 * @member Ext.Array
14307 * @inheritdoc Ext.Array#merge
14308 */\r
14309 ExtArray.union = ExtArray.merge;\r
14310 /**
14311 * Old alias to {@link Ext.Array#min}
14312 * @deprecated 4.0.0 Use {@link Ext.Array#min} instead
14313 * @method
14314 * @member Ext
14315 * @inheritdoc Ext.Array#min
14316 */\r
14317 Ext.min = ExtArray.min;\r
14318 /**
14319 * Old alias to {@link Ext.Array#max}
14320 * @deprecated 4.0.0 Use {@link Ext.Array#max} instead
14321 * @method
14322 * @member Ext
14323 * @inheritdoc Ext.Array#max
14324 */\r
14325 Ext.max = ExtArray.max;\r
14326 /**
14327 * Old alias to {@link Ext.Array#sum}
14328 * @deprecated 4.0.0 Use {@link Ext.Array#sum} instead
14329 * @method
14330 * @member Ext
14331 * @inheritdoc Ext.Array#sum
14332 */\r
14333 Ext.sum = ExtArray.sum;\r
14334 /**
14335 * Old alias to {@link Ext.Array#mean}
14336 * @deprecated 4.0.0 Use {@link Ext.Array#mean} instead
14337 * @method
14338 * @member Ext
14339 * @inheritdoc Ext.Array#mean
14340 */\r
14341 Ext.mean = ExtArray.mean;\r
14342 /**
14343 * Old alias to {@link Ext.Array#flatten}
14344 * @deprecated 4.0.0 Use {@link Ext.Array#flatten} instead
14345 * @method
14346 * @member Ext
14347 * @inheritdoc Ext.Array#flatten
14348 */\r
14349 Ext.flatten = ExtArray.flatten;\r
14350 /**
14351 * Old alias to {@link Ext.Array#clean}
14352 * @deprecated 4.0.0 Use {@link Ext.Array#clean} instead
14353 * @method
14354 * @member Ext
14355 * @inheritdoc Ext.Array#clean
14356 */\r
14357 Ext.clean = ExtArray.clean;\r
14358 /**
14359 * Old alias to {@link Ext.Array#unique}
14360 * @deprecated 4.0.0 Use {@link Ext.Array#unique} instead
14361 * @method
14362 * @member Ext
14363 * @inheritdoc Ext.Array#unique
14364 */\r
14365 Ext.unique = ExtArray.unique;\r
14366 /**
14367 * Old alias to {@link Ext.Array#pluck Ext.Array.pluck}
14368 * @deprecated 4.0.0 Use {@link Ext.Array#pluck Ext.Array.pluck} instead
14369 * @method
14370 * @member Ext
14371 * @inheritdoc Ext.Array#pluck
14372 */\r
14373 Ext.pluck = ExtArray.pluck;\r
14374 /**
14375 * @method
14376 * @member Ext
14377 * @inheritdoc Ext.Array#toArray
14378 */\r
14379 Ext.toArray = function() {\r
14380 return ExtArray.toArray.apply(ExtArray, arguments);\r
14381 };\r
14382 return ExtArray;\r
14383}());\r
14384\r
14385// @define Ext.lang.Assert\r
14386// @define Ext.Assert\r
14387// @require Ext.lang.Error\r
14388/**
14389 * @class Ext.Assert
14390 * This class provides help value testing methods useful for diagnostics. These are often
14391 * used in `debugHooks`:
14392 *
14393 * Ext.define('Foo.bar.Class', {
14394 *
14395 * debugHooks: {
14396 * method: function (a) {
14397 * Ext.Assert.truthy(a, 'Expected "a" to be truthy');
14398 * },
14399 *
14400 * foo: function (object) {
14401 * Ext.Assert.isFunctionProp(object, 'doSomething');
14402 * }
14403 * }
14404 * });
14405 *
14406 * **NOTE:** This class is entirely removed in production builds so all uses of it should
14407 * be either in `debug` conditional comments or `debugHooks`.
14408 *
14409 * The following type detection methods from the `Ext` object are wrapped as assertions
14410 * by this class:
14411 *
14412 * * `isEmpty`
14413 * * `isArray`
14414 * * `isDate`
14415 * * `isObject`
14416 * * `isSimpleObject`
14417 * * `isPrimitive`
14418 * * `isFunction`
14419 * * `isNumber`
14420 * * `isNumeric`
14421 * * `isString`
14422 * * `isBoolean`
14423 * * `isElement`
14424 * * `isTextNode`
14425 * * `isDefined`
14426 * * `isIterable`
14427 *
14428 * These appear both their exact name and with a "Prop" suffix for checking a property on
14429 * an object. For example, these are almost identical:
14430 *
14431 * Ext.Assert.isFunction(object.foo);
14432 *
14433 * Ext.Assert.isFunctionProp(object, 'foo');
14434 *
14435 * The difference is the default error message generated is better in the second use case
14436 * than the first.
14437 *
14438 * The above list are also expanded for "Not" flavors (and "Not...Prop"):
14439 *
14440 * * `isNotEmpty`
14441 * * `isNotArray`
14442 * * `isNotDate`
14443 * * `isNotObject`
14444 * * `isNotSimpleObject`
14445 * * `isNotPrimitive`
14446 * * `isNotFunction`
14447 * * `isNotNumber`
14448 * * `isNotNumeric`
14449 * * `isNotString`
14450 * * `isNotBoolean`
14451 * * `isNotElement`
14452 * * `isNotTextNode`
14453 * * `isNotDefined`
14454 * * `isNotIterable`
14455 */\r
14456Ext.Assert = {\r
14457 /**
14458 * Checks that the first argument is falsey and throws an `Error` if it is not.
14459 */\r
14460 falsey: function(b, msg) {\r
14461 if (b) {\r
14462 Ext.raise(msg || ('Expected a falsey value but was ' + b));\r
14463 }\r
14464 },\r
14465 /**
14466 * Checks that the first argument is falsey and throws an `Error` if it is not.
14467 */\r
14468 falseyProp: function(object, property) {\r
14469 Ext.Assert.truthy(object);\r
14470 var b = object[property];\r
14471 if (b) {\r
14472 if (object.$className) {\r
14473 property = object.$className + '#' + property;\r
14474 }\r
14475 Ext.raise('Expected a falsey value for ' + property + ' but was ' + b);\r
14476 }\r
14477 },\r
14478 /**
14479 * Checks that the first argument is truthy and throws an `Error` if it is not.
14480 */\r
14481 truthy: function(b, msg) {\r
14482 if (!b) {\r
14483 Ext.raise(msg || ('Expected a truthy value but was ' + typeof b));\r
14484 }\r
14485 },\r
14486 /**
14487 * Checks that the first argument is truthy and throws an `Error` if it is not.
14488 */\r
14489 truthyProp: function(object, property) {\r
14490 Ext.Assert.truthy(object);\r
14491 var b = object[property];\r
14492 if (!b) {\r
14493 if (object.$className) {\r
14494 property = object.$className + '#' + property;\r
14495 }\r
14496 Ext.raise('Expected a truthy value for ' + property + ' but was ' + typeof b);\r
14497 }\r
14498 }\r
14499};\r
14500(function() {\r
14501 function makeAssert(name, kind) {\r
14502 var testFn = Ext[name],\r
14503 def;\r
14504 return function(value, msg) {\r
14505 if (!testFn(value)) {\r
14506 Ext.raise(msg || def || (def = 'Expected value to be ' + kind));\r
14507 }\r
14508 };\r
14509 }\r
14510 function makeAssertProp(name, kind) {\r
14511 var testFn = Ext[name],\r
14512 def;\r
14513 return function(object, prop) {\r
14514 Ext.Assert.truthy(object);\r
14515 if (!testFn(object[prop])) {\r
14516 Ext.raise(def || (def = 'Expected ' + (object.$className ? object.$className + '#' : '') + prop + ' to be ' + kind));\r
14517 }\r
14518 };\r
14519 }\r
14520 function makeNotAssert(name, kind) {\r
14521 var testFn = Ext[name],\r
14522 def;\r
14523 return function(value, msg) {\r
14524 if (testFn(value)) {\r
14525 Ext.raise(msg || def || (def = 'Expected value to NOT be ' + kind));\r
14526 }\r
14527 };\r
14528 }\r
14529 function makeNotAssertProp(name, kind) {\r
14530 var testFn = Ext[name],\r
14531 def;\r
14532 return function(object, prop) {\r
14533 Ext.Assert.truthy(object);\r
14534 if (testFn(object[prop])) {\r
14535 Ext.raise(def || (def = 'Expected ' + (object.$className ? object.$className + '#' : '') + prop + ' to NOT be ' + kind));\r
14536 }\r
14537 };\r
14538 }\r
14539 for (var name in Ext) {\r
14540 if (name.substring(0, 2) == "is" && Ext.isFunction(Ext[name])) {\r
14541 var kind = name.substring(2);\r
14542 Ext.Assert[name] = makeAssert(name, kind);\r
14543 Ext.Assert[name + 'Prop'] = makeAssertProp(name, kind);\r
14544 Ext.Assert['isNot' + kind] = makeNotAssert(name, kind);\r
14545 Ext.Assert['isNot' + kind + 'Prop'] = makeNotAssertProp(name, kind);\r
14546 }\r
14547 }\r
14548}());\r
14549\r
14550/**
14551 * @class Ext.String
14552 *
14553 * A collection of useful static methods to deal with strings.
14554 * @singleton
14555 */\r
14556Ext.String = (function() {\r
14557 // @define Ext.lang.String\r
14558 // @define Ext.String\r
14559 // @require Ext\r
14560 // @require Ext.lang.Array\r
14561 var trimRegex = /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,\r
14562 escapeRe = /('|\\)/g,\r
14563 escapeRegexRe = /([-.*+?\^${}()|\[\]\/\\])/g,\r
14564 basicTrimRe = /^\s+|\s+$/g,\r
14565 whitespaceRe = /\s+/,\r
14566 varReplace = /(^[^a-z]*|[^\w])/gi,\r
14567 charToEntity, entityToChar, charToEntityRegex, entityToCharRegex,\r
14568 htmlEncodeReplaceFn = function(match, capture) {\r
14569 return charToEntity[capture];\r
14570 },\r
14571 htmlDecodeReplaceFn = function(match, capture) {\r
14572 return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));\r
14573 },\r
14574 boundsCheck = function(s, other) {\r
14575 if (s === null || s === undefined || other === null || other === undefined) {\r
14576 return false;\r
14577 }\r
14578 return other.length <= s.length;\r
14579 },\r
14580 ExtString;\r
14581 return ExtString = {\r
14582 /**
14583 * Inserts a substring into a string.
14584 * @param {String} s The original string.
14585 * @param {String} value The substring to insert.
14586 * @param {Number} index The index to insert the substring. Negative indexes will insert from the end of
14587 * the string. Example:
14588 *
14589 * Ext.String.insert("abcdefg", "h", -1); // abcdefhg
14590 *
14591 * @return {String} The value with the inserted substring
14592 */\r
14593 insert: function(s, value, index) {\r
14594 if (!s) {\r
14595 return value;\r
14596 }\r
14597 if (!value) {\r
14598 return s;\r
14599 }\r
14600 var len = s.length;\r
14601 if (!index && index !== 0) {\r
14602 index = len;\r
14603 }\r
14604 if (index < 0) {\r
14605 index *= -1;\r
14606 if (index >= len) {\r
14607 // negative overflow, insert at start\r
14608 index = 0;\r
14609 } else {\r
14610 index = len - index;\r
14611 }\r
14612 }\r
14613 if (index === 0) {\r
14614 s = value + s;\r
14615 } else if (index >= s.length) {\r
14616 s += value;\r
14617 } else {\r
14618 s = s.substr(0, index) + value + s.substr(index);\r
14619 }\r
14620 return s;\r
14621 },\r
14622 /**
14623 * Checks if a string starts with a substring
14624 * @param {String} s The original string
14625 * @param {String} start The substring to check
14626 * @param {Boolean} [ignoreCase=false] True to ignore the case in the comparison
14627 */\r
14628 startsWith: function(s, start, ignoreCase) {\r
14629 var result = boundsCheck(s, start);\r
14630 if (result) {\r
14631 if (ignoreCase) {\r
14632 s = s.toLowerCase();\r
14633 start = start.toLowerCase();\r
14634 }\r
14635 result = s.lastIndexOf(start, 0) === 0;\r
14636 }\r
14637 return result;\r
14638 },\r
14639 /**
14640 * Checks if a string ends with a substring
14641 * @param {String} s The original string
14642 * @param {String} end The substring to check
14643 * @param {Boolean} [ignoreCase=false] True to ignore the case in the comparison
14644 */\r
14645 endsWith: function(s, end, ignoreCase) {\r
14646 var result = boundsCheck(s, end);\r
14647 if (result) {\r
14648 if (ignoreCase) {\r
14649 s = s.toLowerCase();\r
14650 end = end.toLowerCase();\r
14651 }\r
14652 result = s.indexOf(end, s.length - end.length) !== -1;\r
14653 }\r
14654 return result;\r
14655 },\r
14656 /**
14657 * Converts a string of characters into a legal, parse-able JavaScript `var` name as long as the passed
14658 * string contains at least one alphabetic character. Non alphanumeric characters, and *leading* non alphabetic
14659 * characters will be removed.
14660 * @param {String} s A string to be converted into a `var` name.
14661 * @return {String} A legal JavaScript `var` name.
14662 */\r
14663 createVarName: function(s) {\r
14664 return s.replace(varReplace, '');\r
14665 },\r
14666 /**
14667 * Convert certain characters (&, <, >, ', and ") to their HTML character equivalents for literal display in web pages.
14668 * @param {String} value The string to encode.
14669 * @return {String} The encoded text.
14670 * @method
14671 */\r
14672 htmlEncode: function(value) {\r
14673 return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);\r
14674 },\r
14675 /**
14676 * Convert certain characters (&, <, >, ', and ") from their HTML character equivalents.
14677 * @param {String} value The string to decode.
14678 * @return {String} The decoded text.
14679 * @method
14680 */\r
14681 htmlDecode: function(value) {\r
14682 return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);\r
14683 },\r
14684 /**
14685 * Checks if a string has values needing to be html encoded.
14686 * @private
14687 * @param {String} s The string to test
14688 * @return {Boolean} `true` if the string contains HTML characters
14689 */\r
14690 hasHtmlCharacters: function(s) {\r
14691 return charToEntityRegex.test(s);\r
14692 },\r
14693 /**
14694 * Adds a set of character entity definitions to the set used by
14695 * {@link Ext.String#htmlEncode} and {@link Ext.String#htmlDecode}.
14696 *
14697 * This object should be keyed by the entity name sequence,
14698 * with the value being the textual representation of the entity.
14699 *
14700 * Ext.String.addCharacterEntities({
14701 * '&amp;Uuml;':'Ü',
14702 * '&amp;ccedil;':'ç',
14703 * '&amp;ntilde;':'ñ',
14704 * '&amp;egrave;':'è'
14705 * });
14706 * var s = Ext.String.htmlEncode("A string with entities: èÜçñ");
14707 *
14708 * __Note:__ the values of the character entities defined on this object are expected
14709 * to be single character values. As such, the actual values represented by the
14710 * characters are sensitive to the character encoding of the JavaScript source
14711 * file when defined in string literal form. Script tags referencing server
14712 * resources with character entities must ensure that the 'charset' attribute
14713 * of the script node is consistent with the actual character encoding of the
14714 * server resource.
14715 *
14716 * The set of character entities may be reset back to the default state by using
14717 * the {@link Ext.String#resetCharacterEntities} method
14718 *
14719 * @param {Object} newEntities The set of character entities to add to the current
14720 * definitions.
14721 */\r
14722 addCharacterEntities: function(newEntities) {\r
14723 var charKeys = [],\r
14724 entityKeys = [],\r
14725 key, echar;\r
14726 for (key in newEntities) {\r
14727 echar = newEntities[key];\r
14728 entityToChar[key] = echar;\r
14729 charToEntity[echar] = key;\r
14730 charKeys.push(echar);\r
14731 entityKeys.push(key);\r
14732 }\r
14733 charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');\r
14734 entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');\r
14735 },\r
14736 /**
14737 * Resets the set of character entity definitions used by
14738 * {@link Ext.String#htmlEncode} and {@link Ext.String#htmlDecode} back to the
14739 * default state.
14740 */\r
14741 resetCharacterEntities: function() {\r
14742 charToEntity = {};\r
14743 entityToChar = {};\r
14744 // add the default set\r
14745 this.addCharacterEntities({\r
14746 '&amp;': '&',\r
14747 '&gt;': '>',\r
14748 '&lt;': '<',\r
14749 '&quot;': '"',\r
14750 '&#39;': "'"\r
14751 });\r
14752 },\r
14753 /**
14754 * Appends content to the query string of a URL, handling logic for whether to place
14755 * a question mark or ampersand.
14756 * @param {String} url The URL to append to.
14757 * @param {String} string The content to append to the URL.
14758 * @return {String} The resulting URL
14759 */\r
14760 urlAppend: function(url, string) {\r
14761 if (!Ext.isEmpty(string)) {\r
14762 return url + (url.indexOf('?') === -1 ? '?' : '&') + string;\r
14763 }\r
14764 return url;\r
14765 },\r
14766 /**
14767 * Trims whitespace from either end of a string, leaving spaces within the string intact. Example:
14768 *
14769 * var s = ' foo bar ';
14770 * alert('-' + s + '-'); //alerts "- foo bar -"
14771 * alert('-' + Ext.String.trim(s) + '-'); //alerts "-foo bar-"
14772 *
14773 * @param {String} string The string to trim.
14774 * @return {String} The trimmed string.
14775 */\r
14776 trim: function(string) {\r
14777 if (string) {\r
14778 string = string.replace(trimRegex, "");\r
14779 }\r
14780 return string || '';\r
14781 },\r
14782 /**
14783 * Capitalize the first letter of the given string.
14784 * @param {String} string
14785 * @return {String}
14786 */\r
14787 capitalize: function(string) {\r
14788 if (string) {\r
14789 string = string.charAt(0).toUpperCase() + string.substr(1);\r
14790 }\r
14791 return string || '';\r
14792 },\r
14793 /**
14794 * Uncapitalize the first letter of a given string.
14795 * @param {String} string
14796 * @return {String}
14797 */\r
14798 uncapitalize: function(string) {\r
14799 if (string) {\r
14800 string = string.charAt(0).toLowerCase() + string.substr(1);\r
14801 }\r
14802 return string || '';\r
14803 },\r
14804 /**
14805 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length.
14806 * @param {String} value The string to truncate.
14807 * @param {Number} length The maximum length to allow before truncating.
14808 * @param {Boolean} [word=false] `true` to try to find a common word break.
14809 * @return {String} The converted text.
14810 */\r
14811 ellipsis: function(value, length, word) {\r
14812 if (value && value.length > length) {\r
14813 if (word) {\r
14814 var vs = value.substr(0, length - 2),\r
14815 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));\r
14816 if (index !== -1 && index >= (length - 15)) {\r
14817 return vs.substr(0, index) + "...";\r
14818 }\r
14819 }\r
14820 return value.substr(0, length - 3) + "...";\r
14821 }\r
14822 return value;\r
14823 },\r
14824 /**
14825 * Escapes the passed string for use in a regular expression.
14826 * @param {String} string The string to escape.
14827 * @return {String} The escaped string.
14828 */\r
14829 escapeRegex: function(string) {\r
14830 return string.replace(escapeRegexRe, "\\$1");\r
14831 },\r
14832 /**
14833 * Creates a `RegExp` given a string `value` and optional flags. For example, the
14834 * following two regular expressions are equivalent.
14835 *
14836 * var regex1 = Ext.String.createRegex('hello');
14837 *
14838 * var regex2 = /^hello$/i;
14839 *
14840 * The following two regular expressions are also equivalent:
14841 *
14842 * var regex1 = Ext.String.createRegex('world', false, false, false);
14843 *
14844 * var regex2 = /world/;
14845 *
14846 * @param {String/RegExp} value The String to convert to a `RegExp`.
14847 * @param {Boolean} [startsWith=true] Pass `false` to allow a match to start
14848 * anywhere in the string. By default the `value` will match only at the start
14849 * of the string.
14850 * @param {Boolean} [endsWith=true] Pass `false` to allow the match to end before
14851 * the end of the string. By default the `value` will match only at the end of the
14852 * string.
14853 * @param {Boolean} [ignoreCase=true] Pass `false` to make the `RegExp` case
14854 * sensitive (removes the 'i' flag).
14855 * @since 5.0.0
14856 * @return {RegExp}
14857 */\r
14858 createRegex: function(value, startsWith, endsWith, ignoreCase) {\r
14859 var ret = value;\r
14860 if (value != null && !value.exec) {\r
14861 // not a regex\r
14862 ret = ExtString.escapeRegex(String(value));\r
14863 if (startsWith !== false) {\r
14864 ret = '^' + ret;\r
14865 }\r
14866 if (endsWith !== false) {\r
14867 ret += '$';\r
14868 }\r
14869 ret = new RegExp(ret, (ignoreCase !== false) ? 'i' : '');\r
14870 }\r
14871 return ret;\r
14872 },\r
14873 /**
14874 * Escapes the passed string for ' and \.
14875 * @param {String} string The string to escape.
14876 * @return {String} The escaped string.
14877 */\r
14878 escape: function(string) {\r
14879 return string.replace(escapeRe, "\\$1");\r
14880 },\r
14881 /**
14882 * Utility function that allows you to easily switch a string between two alternating values. The passed value
14883 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
14884 * they are already different, the first value passed in is returned. Note that this method returns the new value
14885 * but does not change the current string.
14886 *
14887 * // alternate sort directions
14888 * sort = Ext.String.toggle(sort, 'ASC', 'DESC');
14889 *
14890 * // instead of conditional logic:
14891 * sort = (sort === 'ASC' ? 'DESC' : 'ASC');
14892 *
14893 * @param {String} string The current string.
14894 * @param {String} value The value to compare to the current string.
14895 * @param {String} other The new value to use if the string already equals the first value passed in.
14896 * @return {String} The new value.
14897 */\r
14898 toggle: function(string, value, other) {\r
14899 return string === value ? other : value;\r
14900 },\r
14901 /**
14902 * Pads the left side of a string with a specified character. This is especially useful
14903 * for normalizing number and date strings. Example usage:
14904 *
14905 * var s = Ext.String.leftPad('123', 5, '0');
14906 * // s now contains the string: '00123'
14907 *
14908 * @param {String} string The original string.
14909 * @param {Number} size The total length of the output string.
14910 * @param {String} [character=' '] (optional) The character with which to pad the original string.
14911 * @return {String} The padded string.
14912 */\r
14913 leftPad: function(string, size, character) {\r
14914 var result = String(string);\r
14915 character = character || " ";\r
14916 while (result.length < size) {\r
14917 result = character + result;\r
14918 }\r
14919 return result;\r
14920 },\r
14921 /**
14922 * Returns a string with a specified number of repetitions a given string pattern.
14923 * The pattern be separated by a different string.
14924 *
14925 * var s = Ext.String.repeat('---', 4); // = '------------'
14926 * var t = Ext.String.repeat('--', 3, '/'); // = '--/--/--'
14927 *
14928 * @param {String} pattern The pattern to repeat.
14929 * @param {Number} count The number of times to repeat the pattern (may be 0).
14930 * @param {String} sep An option string to separate each pattern.
14931 */\r
14932 repeat: function(pattern, count, sep) {\r
14933 if (count < 1) {\r
14934 count = 0;\r
14935 }\r
14936 for (var buf = [],\r
14937 i = count; i--; ) {\r
14938 buf.push(pattern);\r
14939 }\r
14940 return buf.join(sep || '');\r
14941 },\r
14942 /**
14943 * Splits a string of space separated words into an array, trimming as needed. If the
14944 * words are already an array, it is returned.
14945 *
14946 * @param {String/Array} words
14947 */\r
14948 splitWords: function(words) {\r
14949 if (words && typeof words == 'string') {\r
14950 return words.replace(basicTrimRe, '').split(whitespaceRe);\r
14951 }\r
14952 return words || [];\r
14953 }\r
14954 };\r
14955}());\r
14956// initialize the default encode / decode entities\r
14957Ext.String.resetCharacterEntities();\r
14958/**
14959 * Old alias to {@link Ext.String#htmlEncode}
14960 * @deprecated Use {@link Ext.String#htmlEncode} instead
14961 * @method
14962 * @member Ext
14963 * @inheritdoc Ext.String#htmlEncode
14964 */\r
14965Ext.htmlEncode = Ext.String.htmlEncode;\r
14966/**
14967 * Old alias to {@link Ext.String#htmlDecode}
14968 * @deprecated Use {@link Ext.String#htmlDecode} instead
14969 * @method
14970 * @member Ext
14971 * @inheritdoc Ext.String#htmlDecode
14972 */\r
14973Ext.htmlDecode = Ext.String.htmlDecode;\r
14974/**
14975 * Old alias to {@link Ext.String#urlAppend}
14976 * @deprecated Use {@link Ext.String#urlAppend} instead
14977 * @method
14978 * @member Ext
14979 * @inheritdoc Ext.String#urlAppend
14980 */\r
14981Ext.urlAppend = Ext.String.urlAppend;\r
14982\r
14983/**
14984 * @class Ext.Date
14985 * This class defines some basic methods for handling dates.
14986 *
14987 * The date parsing and formatting syntax contains a subset of
14988 * [PHP's `date()` function](http://www.php.net/date), and the formats that are
14989 * supported will provide results equivalent to their PHP versions.
14990 *
14991 * The following is a list of all currently supported formats:
14992 *
14993 * Format Description Example returned values
14994 * ------ ----------------------------------------------------------------------- -----------------------
14995 * d Day of the month, 2 digits with leading zeros 01 to 31
14996 * D A short textual representation of the day of the week Mon to Sun
14997 * j Day of the month without leading zeros 1 to 31
14998 * l A full textual representation of the day of the week Sunday to Saturday
14999 * N ISO-8601 numeric representation of the day of the week 1 (for Monday) through 7 (for Sunday)
15000 * S English ordinal suffix for the day of the month, 2 characters st, nd, rd or th. Works well with j
15001 * w Numeric representation of the day of the week 0 (for Sunday) to 6 (for Saturday)
15002 * z The day of the year (starting from 0) 0 to 364 (365 in leap years)
15003 * W ISO-8601 week number of year, weeks starting on Monday 01 to 53
15004 * F A full textual representation of a month, such as January or March January to December
15005 * m Numeric representation of a month, with leading zeros 01 to 12
15006 * M A short textual representation of a month Jan to Dec
15007 * n Numeric representation of a month, without leading zeros 1 to 12
15008 * t Number of days in the given month 28 to 31
15009 * L Whether it&#39;s a leap year 1 if it is a leap year, 0 otherwise.
15010 * o ISO-8601 year number (identical to (Y), but if the ISO week number (W) Examples: 1998 or 2004
15011 * belongs to the previous or next year, that year is used instead)
15012 * Y A full numeric representation of a year, 4 digits Examples: 1999 or 2003
15013 * y A two digit representation of a year Examples: 99 or 03
15014 * a Lowercase Ante meridiem and Post meridiem am or pm
15015 * A Uppercase Ante meridiem and Post meridiem AM or PM
15016 * g 12-hour format of an hour without leading zeros 1 to 12
15017 * G 24-hour format of an hour without leading zeros 0 to 23
15018 * h 12-hour format of an hour with leading zeros 01 to 12
15019 * H 24-hour format of an hour with leading zeros 00 to 23
15020 * i Minutes, with leading zeros 00 to 59
15021 * s Seconds, with leading zeros 00 to 59
15022 * u Decimal fraction of a second Examples:
15023 * (minimum 1 digit, arbitrary number of digits allowed) 001 (i.e. 0.001s) or
15024 * 100 (i.e. 0.100s) or
15025 * 999 (i.e. 0.999s) or
15026 * 999876543210 (i.e. 0.999876543210s)
15027 * O Difference to Greenwich time (GMT) in hours and minutes Example: +1030
15028 * P Difference to Greenwich time (GMT) with colon between hours and minutes Example: -08:00
15029 * T Timezone abbreviation of the machine running the code Examples: EST, MDT, PDT ...
15030 * Z Timezone offset in seconds (negative if west of UTC, positive if east) -43200 to 50400
15031 * c ISO 8601 date represented as the local time with an offset to UTC appended.
15032 * Notes: Examples:
15033 * 1) If unspecified, the month / day defaults to the current month / day, 1991 or
15034 * the time defaults to midnight, while the timezone defaults to the 1992-10 or
15035 * browser's timezone. If a time is specified, it must include both hours 1993-09-20 or
15036 * and minutes. The "T" delimiter, seconds, milliseconds and timezone 1994-08-19T16:20+01:00 or
15037 * are optional. 1995-07-18T17:21:28-02:00 or
15038 * 2) The decimal fraction of a second, if specified, must contain at 1996-06-17T18:22:29.98765+03:00 or
15039 * least 1 digit (there is no limit to the maximum number 1997-05-16T19:23:30,12345-0400 or
15040 * of digits allowed), and may be delimited by either a '.' or a ',' 1998-04-15T20:24:31.2468Z or
15041 * Refer to the examples on the right for the various levels of 1999-03-14T20:24:32Z or
15042 * date-time granularity which are supported, or see 2000-02-13T21:25:33
15043 * http://www.w3.org/TR/NOTE-datetime for more info. 2001-01-12 22:26:34
15044 * C An ISO date string as implemented by the native Date object's 1962-06-17T09:21:34.125Z
15045 * [Date.toISOString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
15046 * method. This outputs the numeric part with *UTC* hour and minute
15047 * values, and indicates this by appending the `'Z'` timezone
15048 * identifier.
15049 * U Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) 1193432466 or -2138434463
15050 * MS Microsoft AJAX serialized dates \/Date(1238606590509)\/ (i.e. UTC milliseconds since epoch) or
15051 * \/Date(1238606590509+0800)\/
15052 * time A javascript millisecond timestamp 1350024476440
15053 * timestamp A UNIX timestamp (same as U) 1350024866
15054 *
15055 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
15056 *
15057 * // Sample date:
15058 * // 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
15059 *
15060 * var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
15061 * console.log(Ext.Date.format(dt, 'Y-m-d')); // 2007-01-10
15062 * console.log(Ext.Date.format(dt, 'F j, Y, g:i a')); // January 10, 2007, 3:05 pm
15063 * console.log(Ext.Date.format(dt, 'l, \\t\\he jS \\of F Y h:i:s A')); // Wednesday, the 10th of January 2007 03:05:01 PM
15064 *
15065 * Here are some standard date/time patterns that you might find helpful. They
15066 * are not part of the source of Ext.Date, but to use them you can simply copy this
15067 * block of code into any script that is included after Ext.Date and they will also become
15068 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
15069 *
15070 * Ext.Date.patterns = {
15071 * ISO8601Long:"Y-m-d H:i:s",
15072 * ISO8601Short:"Y-m-d",
15073 * ShortDate: "n/j/Y",
15074 * LongDate: "l, F d, Y",
15075 * FullDateTime: "l, F d, Y g:i:s A",
15076 * MonthDay: "F d",
15077 * ShortTime: "g:i A",
15078 * LongTime: "g:i:s A",
15079 * SortableDateTime: "Y-m-d\\TH:i:s",
15080 * UniversalSortableDateTime: "Y-m-d H:i:sO",
15081 * YearMonth: "F, Y"
15082 * };
15083 *
15084 * Example usage:
15085 *
15086 * var dt = new Date();
15087 * console.log(Ext.Date.format(dt, Ext.Date.patterns.ShortDate));
15088 *
15089 * Developer-written, custom formats may be used by supplying both a formatting and a parsing function
15090 * which perform to specialized requirements. The functions are stored in {@link #parseFunctions} and {@link #formatFunctions}.
15091 * @singleton
15092 */\r
15093Ext.Date = (function() {\r
15094 // @define Ext.lang.Date\r
15095 // @define Ext.Date\r
15096 // @require Ext\r
15097 // @require Ext.lang.String\r
15098 var utilDate,\r
15099 nativeDate = Date,\r
15100 stripEscapeRe = /(\\.)/g,\r
15101 hourInfoRe = /([gGhHisucUOPZ]|MS)/,\r
15102 dateInfoRe = /([djzmnYycU]|MS)/,\r
15103 slashRe = /\\/gi,\r
15104 numberTokenRe = /\{(\d+)\}/g,\r
15105 MSFormatRe = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/'),\r
15106 pad = Ext.String.leftPad,\r
15107 // Most of the date-formatting functions below are the excellent work of Baron Schwartz.\r
15108 // (see http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/)\r
15109 // They generate precompiled functions from format patterns instead of parsing and\r
15110 // processing each pattern every time a date is formatted.\r
15111 code = [\r
15112 // date calculations (note: the code below creates a dependency on Ext.Number.from())\r
15113 "var me = this, dt, y, m, d, h, i, s, ms, o, O, z, zz, u, v, W, year, jan4, week1monday, daysInMonth, dayMatched,",\r
15114 "def = me.defaults,",\r
15115 "from = Ext.Number.from,",\r
15116 "results = String(input).match(me.parseRegexes[{0}]);",\r
15117 // either null, or an array of matched strings\r
15118 "if(results){",\r
15119 "{1}",\r
15120 "if(u != null){",\r
15121 // i.e. unix time is defined\r
15122 "v = new Date(u * 1000);",\r
15123 // give top priority to UNIX time\r
15124 "}else{",\r
15125 // create Date object representing midnight of the current day;\r
15126 // this will provide us with our date defaults\r
15127 // (note: clearTime() handles Daylight Saving Time automatically)\r
15128 "dt = me.clearTime(new Date);",\r
15129 "y = from(y, from(def.y, dt.getFullYear()));",\r
15130 "m = from(m, from(def.m - 1, dt.getMonth()));",\r
15131 "dayMatched = d !== undefined;",\r
15132 "d = from(d, from(def.d, dt.getDate()));",\r
15133 // Attempt to validate the day. Since it defaults to today, it may go out\r
15134 // of range, for example parsing m/Y where the value is 02/2000 on the 31st of May.\r
15135 // It will attempt to parse 2000/02/31, which will overflow to March and end up\r
15136 // returning 03/2000. We only do this when we default the day. If an invalid day value\r
15137 // was set to be parsed by the user, continue on and either let it overflow or return null\r
15138 // depending on the strict value. This will be in line with the normal Date behaviour.\r
15139 "if (!dayMatched) {",\r
15140 "dt.setDate(1);",\r
15141 "dt.setMonth(m);",\r
15142 "dt.setFullYear(y);",\r
15143 "daysInMonth = me.getDaysInMonth(dt);",\r
15144 "if (d > daysInMonth) {",\r
15145 "d = daysInMonth;",\r
15146 "}",\r
15147 "}",\r
15148 "h = from(h, from(def.h, dt.getHours()));",\r
15149 "i = from(i, from(def.i, dt.getMinutes()));",\r
15150 "s = from(s, from(def.s, dt.getSeconds()));",\r
15151 "ms = from(ms, from(def.ms, dt.getMilliseconds()));",\r
15152 "if(z >= 0 && y >= 0){",\r
15153 // both the year and zero-based day of year are defined and >= 0.\r
15154 // these 2 values alone provide sufficient info to create a full date object\r
15155 // create Date object representing January 1st for the given year\r
15156 // handle years < 100 appropriately\r
15157 "v = me.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), me.YEAR, y < 100 ? y - 100 : 0);",\r
15158 // then add day of year, checking for Date "rollover" if necessary\r
15159 "v = !strict? v : (strict === true && (z <= 364 || (me.isLeapYear(v) && z <= 365))? me.add(v, me.DAY, z) : null);",\r
15160 "}else if(strict === true && !me.isValid(y, m + 1, d, h, i, s, ms)){",\r
15161 // check for Date "rollover"\r
15162 "v = null;",\r
15163 // invalid date, so return null\r
15164 "}else{",\r
15165 "if (W) {",\r
15166 // support ISO-8601\r
15167 // http://en.wikipedia.org/wiki/ISO_week_date\r
15168 //\r
15169 // Mutually equivalent definitions for week 01 are:\r
15170 // a. the week starting with the Monday which is nearest in time to 1 January\r
15171 // b. the week with 4 January in it\r
15172 // ... there are many others ...\r
15173 //\r
15174 // We'll use letter b above to determine the first week of the year.\r
15175 //\r
15176 // So, first get a Date object for January 4th of whatever calendar year is desired.\r
15177 //\r
15178 // Then, the first Monday of the year can easily be determined by (operating on this Date):\r
15179 // 1. Getting the day of the week.\r
15180 // 2. Subtracting that by one.\r
15181 // 3. Multiplying that by 86400000 (one day in ms).\r
15182 // 4. Subtracting this number of days (in ms) from the January 4 date (represented in ms).\r
15183 //\r
15184 // Example #1 ...\r
15185 //\r
15186 // January 2012\r
15187 // Su Mo Tu We Th Fr Sa\r
15188 // 1 2 3 4 5 6 7\r
15189 // 8 9 10 11 12 13 14\r
15190 // 15 16 17 18 19 20 21\r
15191 // 22 23 24 25 26 27 28\r
15192 // 29 30 31\r
15193 //\r
15194 // 1. January 4th is a Wednesday.\r
15195 // 2. Its day number is 3.\r
15196 // 3. Simply substract 2 days from Wednesday.\r
15197 // 4. The first week of the year begins on Monday, January 2. Simple!\r
15198 //\r
15199 // Example #2 ...\r
15200 // January 1992\r
15201 // Su Mo Tu We Th Fr Sa\r
15202 // 1 2 3 4\r
15203 // 5 6 7 8 9 10 11\r
15204 // 12 13 14 15 16 17 18\r
15205 // 19 20 21 22 23 24 25\r
15206 // 26 27 28 29 30 31\r
15207 //\r
15208 // 1. January 4th is a Saturday.\r
15209 // 2. Its day number is 6.\r
15210 // 3. Simply subtract 5 days from Saturday.\r
15211 // 4. The first week of the year begins on Monday, December 30. Simple!\r
15212 //\r
15213 // v = Ext.Date.clearTime(new Date(week1monday.getTime() + ((W - 1) * 604800000 + 43200000)));\r
15214 // (This is essentially doing the same thing as above but for the week rather than the day)\r
15215 "year = y || (new Date()).getFullYear();",\r
15216 "jan4 = new Date(year, 0, 4, 0, 0, 0);",\r
15217 "d = jan4.getDay();",\r
15218 // If the 1st is a Thursday, then the 4th will be a Sunday, so we need the appropriate\r
15219 // day number here, which is why we use the day === checks.\r
15220 "week1monday = new Date(jan4.getTime() - ((d === 0 ? 6 : d - 1) * 86400000));",\r
15221 // The reason for adding 43200000 (12 hours) is to avoid any complication with daylight saving\r
15222 // switch overs. For example, if the clock is rolled back, an hour will repeat, so adding 7 days\r
15223 // will leave us 1 hour short (Sun <date> 23:00:00). By setting is to 12:00, subtraction\r
15224 // or addition of an hour won't make any difference.\r
15225 "v = Ext.Date.clearTime(new Date(week1monday.getTime() + ((W - 1) * 604800000 + 43200000)));",\r
15226 "} else {",\r
15227 // plain old Date object\r
15228 // handle years < 100 properly\r
15229 "v = me.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), me.YEAR, y < 100 ? y - 100 : 0);",\r
15230 "}",\r
15231 "}",\r
15232 "}",\r
15233 "}",\r
15234 "if(v){",\r
15235 // favor UTC offset over GMT offset\r
15236 "if(zz != null){",\r
15237 // reset to UTC, then add offset\r
15238 "v = me.add(v, me.SECOND, -v.getTimezoneOffset() * 60 - zz);",\r
15239 "}else if(o){",\r
15240 // reset to GMT, then add offset\r
15241 "v = me.add(v, me.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",\r
15242 "}",\r
15243 "}",\r
15244 "return (v != null) ? v : null;"\r
15245 ].join('\n');\r
15246 // Polyfill Date's toISOString instance method where not implemented.\r
15247 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString\r
15248 // TODO: Remove this when IE8 retires.\r
15249 if (!Date.prototype.toISOString) {\r
15250 Date.prototype.toISOString = function() {\r
15251 var me = this;\r
15252 return pad(me.getUTCFullYear(), 4, '0') + '-' + pad(me.getUTCMonth() + 1, 2, '0') + '-' + pad(me.getUTCDate(), 2, '0') + 'T' + pad(me.getUTCHours(), 2, '0') + ':' + pad(me.getUTCMinutes(), 2, '0') + ':' + pad(me.getUTCSeconds(), 2, '0') + '.' + pad(me.getUTCMilliseconds(), 3, '0') + 'Z';\r
15253 };\r
15254 }\r
15255 /**
15256 * @private
15257 * Create private copy of Ext JS's `Ext.util.Format.format()` method
15258 * + to remove unnecessary dependency
15259 * + to resolve namespace conflict with MS-Ajax's implementation
15260 */\r
15261 function xf(format) {\r
15262 var args = Array.prototype.slice.call(arguments, 1);\r
15263 return format.replace(numberTokenRe, function(m, i) {\r
15264 return args[i];\r
15265 });\r
15266 }\r
15267 return utilDate = {\r
15268 /** @ignore */\r
15269 now: nativeDate.now,\r
15270 // always available due to polyfill in Ext.js\r
15271 /**
15272 * @private
15273 */\r
15274 toString: function(date) {\r
15275 if (!date) {\r
15276 date = new nativeDate();\r
15277 }\r
15278 return date.getFullYear() + "-" + pad(date.getMonth() + 1, 2, '0') + "-" + pad(date.getDate(), 2, '0') + "T" + pad(date.getHours(), 2, '0') + ":" + pad(date.getMinutes(), 2, '0') + ":" + pad(date.getSeconds(), 2, '0');\r
15279 },\r
15280 /**
15281 * Returns the number of milliseconds between two dates.
15282 * @param {Date} dateA The first date.
15283 * @param {Date} [dateB=new Date()] (optional) The second date.
15284 * @return {Number} The difference in milliseconds
15285 */\r
15286 getElapsed: function(dateA, dateB) {\r
15287 return Math.abs(dateA - (dateB || utilDate.now()));\r
15288 },\r
15289 /**
15290 * Global flag which determines if strict date parsing should be used.
15291 * Strict date parsing will not roll-over invalid dates, which is the
15292 * default behavior of JavaScript Date objects.
15293 * (see {@link #parse} for more information)
15294 * @type Boolean
15295 */\r
15296 useStrict: false,\r
15297 /**
15298 * @private
15299 */\r
15300 formatCodeToRegex: function(character, currentGroup) {\r
15301 // Note: currentGroup - position in regex result array (see notes for Ext.Date.parseCodes below)\r
15302 var p = utilDate.parseCodes[character];\r
15303 if (p) {\r
15304 p = typeof p === 'function' ? p() : p;\r
15305 utilDate.parseCodes[character] = p;\r
15306 }\r
15307 // reassign function result to prevent repeated execution\r
15308 return p ? Ext.applyIf({\r
15309 c: p.c ? xf(p.c, currentGroup || "{0}") : p.c\r
15310 }, p) : {\r
15311 g: 0,\r
15312 c: null,\r
15313 s: Ext.String.escapeRegex(character)\r
15314 };\r
15315 },\r
15316 // treat unrecognized characters as literals\r
15317 /**
15318 * An object hash in which each property is a date parsing function. The property name is the
15319 * format string which that function parses.
15320 *
15321 * This object is automatically populated with date parsing functions as
15322 * date formats are requested for Ext standard formatting strings.
15323 *
15324 * Custom parsing functions may be inserted into this object, keyed by a name which from then on
15325 * may be used as a format string to {@link #parse}.
15326 *
15327 * Example:
15328 *
15329 * Ext.Date.parseFunctions['x-date-format'] = myDateParser;
15330 *
15331 * A parsing function should return a Date object, and is passed the following parameters:
15332 *
15333 * - `date`: {@link String} - The date string to parse.
15334 * - `strict`: {@link Boolean} - `true` to validate date strings while parsing
15335 * (i.e. prevent JavaScript Date "rollover"). __The default must be `false`.__
15336 * Invalid date strings should return `null` when parsed.
15337 *
15338 * To enable Dates to also be _formatted_ according to that format, a corresponding
15339 * formatting function must be placed into the {@link #formatFunctions} property.
15340 * @property parseFunctions
15341 * @type Object
15342 */\r
15343 parseFunctions: {\r
15344 "MS": function(input, strict) {\r
15345 // note: the timezone offset is ignored since the MS Ajax server sends\r
15346 // a UTC milliseconds-since-Unix-epoch value (negative values are allowed)\r
15347 var r = (input || '').match(MSFormatRe);\r
15348 return r ? new nativeDate(((r[1] || '') + r[2]) * 1) : null;\r
15349 },\r
15350 "time": function(input, strict) {\r
15351 var num = parseInt(input, 10);\r
15352 if (num || num === 0) {\r
15353 return new nativeDate(num);\r
15354 }\r
15355 return null;\r
15356 },\r
15357 "timestamp": function(input, strict) {\r
15358 var num = parseInt(input, 10);\r
15359 if (num || num === 0) {\r
15360 return new nativeDate(num * 1000);\r
15361 }\r
15362 return null;\r
15363 }\r
15364 },\r
15365 parseRegexes: [],\r
15366 /**
15367 * An object hash in which each property is a date formatting function. The property name is the
15368 * format string which corresponds to the produced formatted date string.
15369 *
15370 * This object is automatically populated with date formatting functions as
15371 * date formats are requested for Ext standard formatting strings.
15372 *
15373 * Custom formatting functions may be inserted into this object, keyed by a name which from then on
15374 * may be used as a format string to {@link #format}.
15375 *
15376 * Example:
15377 *
15378 * Ext.Date.formatFunctions['x-date-format'] = myDateFormatter;
15379 *
15380 * A formatting function should return a string representation of the Date object which
15381 * is the scope (this) of the function.
15382 *
15383 * To enable date strings to also be _parsed_ according to that format, a corresponding
15384 * parsing function must be placed into the {@link #parseFunctions} property.
15385 * @property formatFunctions
15386 * @type Object
15387 */\r
15388 formatFunctions: {\r
15389 "MS": function() {\r
15390 // UTC milliseconds since Unix epoch (MS-AJAX serialized date format (MRSF))\r
15391 return '\\/Date(' + this.getTime() + ')\\/';\r
15392 },\r
15393 "time": function() {\r
15394 return this.getTime().toString();\r
15395 },\r
15396 "timestamp": function() {\r
15397 return utilDate.format(this, 'U');\r
15398 }\r
15399 },\r
15400 y2kYear: 50,\r
15401 /**
15402 * Date interval constant.
15403 * @type String
15404 */\r
15405 MILLI: "ms",\r
15406 /**
15407 * Date interval constant.
15408 * @type String
15409 */\r
15410 SECOND: "s",\r
15411 /**
15412 * Date interval constant.
15413 * @type String
15414 */\r
15415 MINUTE: "mi",\r
15416 /** Date interval constant.
15417 * @type String
15418 */\r
15419 HOUR: "h",\r
15420 /**
15421 * Date interval constant.
15422 * @type String
15423 */\r
15424 DAY: "d",\r
15425 /**
15426 * Date interval constant.
15427 * @type String
15428 */\r
15429 MONTH: "mo",\r
15430 /**
15431 * Date interval constant.
15432 * @type String
15433 */\r
15434 YEAR: "y",\r
15435 /**
15436 * An object hash containing default date values used during date parsing.
15437 *
15438 * The following properties are available:
15439 *
15440 * - `y`: {@link Number} - The default year value. Defaults to `undefined`.
15441 * - `m`: {@link Number} - The default 1-based month value. Defaults to `undefined`.
15442 * - `d`: {@link Number} - The default day value. Defaults to `undefined`.
15443 * - `h`: {@link Number} - The default hour value. Defaults to `undefined`.
15444 * - `i`: {@link Number} - The default minute value. Defaults to `undefined`.
15445 * - `s`: {@link Number} - The default second value. Defaults to `undefined`.
15446 * - `ms`: {@link Number} - The default millisecond value. Defaults to `undefined`.
15447 *
15448 * Override these properties to customize the default date values used by the {@link #parse} method.
15449 *
15450 * __Note:__ In countries which experience Daylight Saving Time (i.e. DST), the `h`, `i`, `s`
15451 * and `ms` properties may coincide with the exact time in which DST takes effect.
15452 * It is the responsibility of the developer to account for this.
15453 *
15454 * Example Usage:
15455 *
15456 * // set default day value to the first day of the month
15457 * Ext.Date.defaults.d = 1;
15458 *
15459 * // parse a February date string containing only year and month values.
15460 * // setting the default day value to 1 prevents weird date rollover issues
15461 * // when attempting to parse the following date string on, for example, March 31st 2009.
15462 * Ext.Date.parse('2009-02', 'Y-m'); // returns a Date object representing February 1st 2009.
15463 *
15464 * @property defaults
15465 * @type Object
15466 */\r
15467 defaults: {},\r
15468 //<locale type="array">\r
15469 /**
15470 * @property {String[]} dayNames
15471 * An array of textual day names.
15472 * Override these values for international dates.
15473 *
15474 * Example:
15475 *
15476 * Ext.Date.dayNames = [
15477 * 'SundayInYourLang',
15478 * 'MondayInYourLang'
15479 * // ...
15480 * ];
15481 */\r
15482 dayNames: [\r
15483 "Sunday",\r
15484 "Monday",\r
15485 "Tuesday",\r
15486 "Wednesday",\r
15487 "Thursday",\r
15488 "Friday",\r
15489 "Saturday"\r
15490 ],\r
15491 //</locale>\r
15492 //<locale type="array">\r
15493 /**
15494 * @property {String[]} monthNames
15495 * An array of textual month names.
15496 * Override these values for international dates.
15497 *
15498 * Example:
15499 *
15500 * Ext.Date.monthNames = [
15501 * 'JanInYourLang',
15502 * 'FebInYourLang'
15503 * // ...
15504 * ];
15505 */\r
15506 monthNames: [\r
15507 "January",\r
15508 "February",\r
15509 "March",\r
15510 "April",\r
15511 "May",\r
15512 "June",\r
15513 "July",\r
15514 "August",\r
15515 "September",\r
15516 "October",\r
15517 "November",\r
15518 "December"\r
15519 ],\r
15520 //</locale>\r
15521 //<locale type="object">\r
15522 /**
15523 * @property {Object} monthNumbers
15524 * An object hash of zero-based JavaScript month numbers (with short month names as keys).
15525 *
15526 * __Note:__ keys are case-sensitive.
15527 *
15528 * Override these values for international dates.
15529 *
15530 * Example:
15531 *
15532 * Ext.Date.monthNumbers = {
15533 * 'LongJanNameInYourLang': 0,
15534 * 'ShortJanNameInYourLang':0,
15535 * 'LongFebNameInYourLang':1,
15536 * 'ShortFebNameInYourLang':1
15537 * // ...
15538 * };
15539 */\r
15540 monthNumbers: {\r
15541 January: 0,\r
15542 Jan: 0,\r
15543 February: 1,\r
15544 Feb: 1,\r
15545 March: 2,\r
15546 Mar: 2,\r
15547 April: 3,\r
15548 Apr: 3,\r
15549 May: 4,\r
15550 June: 5,\r
15551 Jun: 5,\r
15552 July: 6,\r
15553 Jul: 6,\r
15554 August: 7,\r
15555 Aug: 7,\r
15556 September: 8,\r
15557 Sep: 8,\r
15558 October: 9,\r
15559 Oct: 9,\r
15560 November: 10,\r
15561 Nov: 10,\r
15562 December: 11,\r
15563 Dec: 11\r
15564 },\r
15565 //</locale>\r
15566 //<locale>\r
15567 /**
15568 * @property {String} defaultFormat
15569 * The date format string that the {@link Ext.util.Format#dateRenderer}
15570 * and {@link Ext.util.Format#date} functions use. See {@link Ext.Date} for details.
15571 *
15572 * This may be overridden in a locale file.
15573 */\r
15574 defaultFormat: "m/d/Y",\r
15575 //</locale>\r
15576 //<locale type="function">\r
15577 /**
15578 * Get the short month name for the given month number.
15579 * Override this function for international dates.
15580 * @param {Number} month A zero-based JavaScript month number.
15581 * @return {String} The short month name.
15582 */\r
15583 getShortMonthName: function(month) {\r
15584 return utilDate.monthNames[month].substring(0, 3);\r
15585 },\r
15586 //</locale>\r
15587 //<locale type="function">\r
15588 /**
15589 * Get the short day name for the given day number.
15590 * Override this function for international dates.
15591 * @param {Number} day A zero-based JavaScript day number.
15592 * @return {String} The short day name.
15593 */\r
15594 getShortDayName: function(day) {\r
15595 return utilDate.dayNames[day].substring(0, 3);\r
15596 },\r
15597 //</locale>\r
15598 //<locale type="function">\r
15599 /**
15600 * Get the zero-based JavaScript month number for the given short/full month name.
15601 * Override this function for international dates.
15602 * @param {String} name The short/full month name.
15603 * @return {Number} The zero-based JavaScript month number.
15604 */\r
15605 getMonthNumber: function(name) {\r
15606 // handle camel casing for English month names (since the keys for the Ext.Date.monthNumbers hash are case sensitive)\r
15607 return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];\r
15608 },\r
15609 //</locale>\r
15610 /**
15611 * Checks if the specified format contains hour information
15612 * @param {String} format The format to check
15613 * @return {Boolean} True if the format contains hour information
15614 * @method
15615 */\r
15616 formatContainsHourInfo: function(format) {\r
15617 return hourInfoRe.test(format.replace(stripEscapeRe, ''));\r
15618 },\r
15619 /**
15620 * Checks if the specified format contains information about
15621 * anything other than the time.
15622 * @param {String} format The format to check
15623 * @return {Boolean} True if the format contains information about
15624 * date/day information.
15625 * @method
15626 */\r
15627 formatContainsDateInfo: function(format) {\r
15628 return dateInfoRe.test(format.replace(stripEscapeRe, ''));\r
15629 },\r
15630 /**
15631 * Removes all escaping for a date format string. In date formats,
15632 * using a '\' can be used to escape special characters.
15633 * @param {String} format The format to unescape
15634 * @return {String} The unescaped format
15635 * @method
15636 */\r
15637 unescapeFormat: function(format) {\r
15638 // Escape the format, since \ can be used to escape special\r
15639 // characters in a date format. For example, in a Spanish\r
15640 // locale the format may be: 'd \\de F \\de Y'\r
15641 return format.replace(slashRe, '');\r
15642 },\r
15643 /**
15644 * The base format-code to formatting-function hashmap used by the {@link #format} method.
15645 * Formatting functions are strings (or functions which return strings) which
15646 * will return the appropriate value when evaluated in the context of the Date object
15647 * from which the {@link #format} method is called.
15648 * Add to / override these mappings for custom date formatting.
15649 *
15650 * __Note:__ `Ext.Date.format()` treats characters as literals if an appropriate mapping cannot be found.
15651 *
15652 * Example:
15653 *
15654 * Ext.Date.formatCodes.x = "Ext.util.Format.leftPad(this.getDate(), 2, '0')";
15655 * console.log(Ext.Date.format(new Date(), 'X'); // returns the current day of the month
15656 * @type Object
15657 */\r
15658 formatCodes: {\r
15659 d: "Ext.String.leftPad(m.getDate(), 2, '0')",\r
15660 D: "Ext.Date.getShortDayName(m.getDay())",\r
15661 // get localized short day name\r
15662 j: "m.getDate()",\r
15663 l: "Ext.Date.dayNames[m.getDay()]",\r
15664 N: "(m.getDay() ? m.getDay() : 7)",\r
15665 S: "Ext.Date.getSuffix(m)",\r
15666 w: "m.getDay()",\r
15667 z: "Ext.Date.getDayOfYear(m)",\r
15668 W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(m), 2, '0')",\r
15669 F: "Ext.Date.monthNames[m.getMonth()]",\r
15670 m: "Ext.String.leftPad(m.getMonth() + 1, 2, '0')",\r
15671 M: "Ext.Date.getShortMonthName(m.getMonth())",\r
15672 // get localized short month name\r
15673 n: "(m.getMonth() + 1)",\r
15674 t: "Ext.Date.getDaysInMonth(m)",\r
15675 L: "(Ext.Date.isLeapYear(m) ? 1 : 0)",\r
15676 o: "(m.getFullYear() + (Ext.Date.getWeekOfYear(m) == 1 && m.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(m) >= 52 && m.getMonth() < 11 ? -1 : 0)))",\r
15677 Y: "Ext.String.leftPad(m.getFullYear(), 4, '0')",\r
15678 y: "('' + m.getFullYear()).substring(2, 4)",\r
15679 a: "(m.getHours() < 12 ? 'am' : 'pm')",\r
15680 A: "(m.getHours() < 12 ? 'AM' : 'PM')",\r
15681 g: "((m.getHours() % 12) ? m.getHours() % 12 : 12)",\r
15682 G: "m.getHours()",\r
15683 h: "Ext.String.leftPad((m.getHours() % 12) ? m.getHours() % 12 : 12, 2, '0')",\r
15684 H: "Ext.String.leftPad(m.getHours(), 2, '0')",\r
15685 i: "Ext.String.leftPad(m.getMinutes(), 2, '0')",\r
15686 s: "Ext.String.leftPad(m.getSeconds(), 2, '0')",\r
15687 u: "Ext.String.leftPad(m.getMilliseconds(), 3, '0')",\r
15688 O: "Ext.Date.getGMTOffset(m)",\r
15689 P: "Ext.Date.getGMTOffset(m, true)",\r
15690 T: "Ext.Date.getTimezone(m)",\r
15691 Z: "(m.getTimezoneOffset() * -60)",\r
15692 c: function() {\r
15693 // ISO-8601 -- GMT format\r
15694 var c = "Y-m-dTH:i:sP",\r
15695 code = [],\r
15696 i,\r
15697 l = c.length,\r
15698 e;\r
15699 for (i = 0; i < l; ++i) {\r
15700 e = c.charAt(i);\r
15701 code.push(e === "T" ? "'T'" : utilDate.getFormatCode(e));\r
15702 }\r
15703 // treat T as a character literal\r
15704 return code.join(" + ");\r
15705 },\r
15706 C: function() {\r
15707 // ISO-1601 -- browser format. UTC numerics with the 'Z' TZ id.\r
15708 return 'm.toISOString()';\r
15709 },\r
15710 U: "Math.round(m.getTime() / 1000)"\r
15711 },\r
15712 /**
15713 * Checks if the passed Date parameters will cause a JavaScript Date "rollover".
15714 * @param {Number} year 4-digit year.
15715 * @param {Number} month 1-based month-of-year.
15716 * @param {Number} day Day of month.
15717 * @param {Number} hour (optional) Hour.
15718 * @param {Number} minute (optional) Minute.
15719 * @param {Number} second (optional) Second.
15720 * @param {Number} millisecond (optional) Millisecond.
15721 * @return {Boolean} `true` if the passed parameters do not cause a Date "rollover", `false` otherwise.
15722 */\r
15723 isValid: function(y, m, d, h, i, s, ms) {\r
15724 // setup defaults\r
15725 h = h || 0;\r
15726 i = i || 0;\r
15727 s = s || 0;\r
15728 ms = ms || 0;\r
15729 // Special handling for year < 100\r
15730 var dt = utilDate.add(new nativeDate(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);\r
15731 return y === dt.getFullYear() && m === dt.getMonth() + 1 && d === dt.getDate() && h === dt.getHours() && i === dt.getMinutes() && s === dt.getSeconds() && ms === dt.getMilliseconds();\r
15732 },\r
15733 /**
15734 * Parses the passed string using the specified date format.
15735 * Note that this function expects normal calendar dates, meaning that months are 1-based (i.e. 1 = January).
15736 * The {@link #defaults} hash will be used for any date value (i.e. year, month, day, hour, minute, second or millisecond)
15737 * which cannot be found in the passed string. If a corresponding default date value has not been specified in the {@link #defaults} hash,
15738 * the current date's year, month, day or DST-adjusted zero-hour time value will be used instead.
15739 * Keep in mind that the input date string must precisely match the specified format string
15740 * in order for the parse operation to be successful (failed parse operations return a
15741 * `null` value).
15742 *
15743 * Example:
15744 *
15745 * //dt = Fri May 25 2007 (current date)
15746 * var dt = new Date();
15747 *
15748 * //dt = Thu May 25 2006 (today&#39;s month/day in 2006)
15749 * dt = Ext.Date.parse("2006", "Y");
15750 *
15751 * //dt = Sun Jan 15 2006 (all date parts specified)
15752 * dt = Ext.Date.parse("2006-01-15", "Y-m-d");
15753 *
15754 * //dt = Sun Jan 15 2006 15:20:01
15755 * dt = Ext.Date.parse("2006-01-15 3:20:01 PM", "Y-m-d g:i:s A");
15756 *
15757 * // attempt to parse Sun Feb 29 2006 03:20:01 in strict mode
15758 * dt = Ext.Date.parse("2006-02-29 03:20:01", "Y-m-d H:i:s", true); // returns null
15759 *
15760 * @param {String} input The raw date string.
15761 * @param {String} format The expected date string format.
15762 * @param {Boolean} [strict=false] (optional) `true` to validate date strings while parsing (i.e. prevents JavaScript Date "rollover").
15763 * Invalid date strings will return `null` when parsed.
15764 * @return {Date/null} The parsed Date, or `null` if an invalid date string.
15765 */\r
15766 parse: function(input, format, strict) {\r
15767 var p = utilDate.parseFunctions;\r
15768 if (p[format] == null) {\r
15769 utilDate.createParser(format);\r
15770 }\r
15771 return p[format].call(utilDate, input, Ext.isDefined(strict) ? strict : utilDate.useStrict);\r
15772 },\r
15773 // Backwards compat\r
15774 parseDate: function(input, format, strict) {\r
15775 return utilDate.parse(input, format, strict);\r
15776 },\r
15777 /**
15778 * @private
15779 */\r
15780 getFormatCode: function(character) {\r
15781 var f = utilDate.formatCodes[character];\r
15782 if (f) {\r
15783 f = typeof f === 'function' ? f() : f;\r
15784 utilDate.formatCodes[character] = f;\r
15785 }\r
15786 // reassign function result to prevent repeated execution\r
15787 // note: unknown characters are treated as literals\r
15788 return f || ("'" + Ext.String.escape(character) + "'");\r
15789 },\r
15790 /**
15791 * @private
15792 */\r
15793 createFormat: function(format) {\r
15794 var code = [],\r
15795 special = false,\r
15796 ch = '',\r
15797 i;\r
15798 for (i = 0; i < format.length; ++i) {\r
15799 ch = format.charAt(i);\r
15800 if (!special && ch === "\\") {\r
15801 special = true;\r
15802 } else if (special) {\r
15803 special = false;\r
15804 code.push("'" + Ext.String.escape(ch) + "'");\r
15805 } else {\r
15806 if (ch === '\n') {\r
15807 code.push("'\\n'");\r
15808 } else {\r
15809 code.push(utilDate.getFormatCode(ch));\r
15810 }\r
15811 }\r
15812 }\r
15813 utilDate.formatFunctions[format] = Ext.functionFactory("var m=this;return " + code.join('+'));\r
15814 },\r
15815 /**
15816 * @private
15817 */\r
15818 createParser: function(format) {\r
15819 var regexNum = utilDate.parseRegexes.length,\r
15820 currentGroup = 1,\r
15821 calc = [],\r
15822 regex = [],\r
15823 special = false,\r
15824 ch = "",\r
15825 i = 0,\r
15826 len = format.length,\r
15827 atEnd = [],\r
15828 obj;\r
15829 for (; i < len; ++i) {\r
15830 ch = format.charAt(i);\r
15831 if (!special && ch === "\\") {\r
15832 special = true;\r
15833 } else if (special) {\r
15834 special = false;\r
15835 regex.push(Ext.String.escape(ch));\r
15836 } else {\r
15837 obj = utilDate.formatCodeToRegex(ch, currentGroup);\r
15838 currentGroup += obj.g;\r
15839 regex.push(obj.s);\r
15840 if (obj.g && obj.c) {\r
15841 if (obj.calcAtEnd) {\r
15842 atEnd.push(obj.c);\r
15843 } else {\r
15844 calc.push(obj.c);\r
15845 }\r
15846 }\r
15847 }\r
15848 }\r
15849 calc = calc.concat(atEnd);\r
15850 utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');\r
15851 utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));\r
15852 },\r
15853 /**
15854 * @private
15855 */\r
15856 parseCodes: {\r
15857 /*
15858 * Notes:
15859 * g = {Number} calculation group (0 or 1. only group 1 contributes to date calculations.)
15860 * c = {String} calculation method (required for group 1. null for group 0. {0} = currentGroup - position in regex result array)
15861 * s = {String} regex pattern. all matches are stored in results[], and are accessible by the calculation mapped to 'c'
15862 */\r
15863 d: {\r
15864 g: 1,\r
15865 c: "d = parseInt(results[{0}], 10);\n",\r
15866 s: "(3[0-1]|[1-2][0-9]|0[1-9])"\r
15867 },\r
15868 // day of month with leading zeroes (01 - 31)\r
15869 j: {\r
15870 g: 1,\r
15871 c: "d = parseInt(results[{0}], 10);\n",\r
15872 s: "(3[0-1]|[1-2][0-9]|[1-9])"\r
15873 },\r
15874 // day of month without leading zeroes (1 - 31)\r
15875 D: function() {\r
15876 for (var a = [],\r
15877 i = 0; i < 7; a.push(utilDate.getShortDayName(i)) , ++i){}\r
15878 // get localised short day names\r
15879 return {\r
15880 g: 0,\r
15881 c: null,\r
15882 s: "(?:" + a.join("|") + ")"\r
15883 };\r
15884 },\r
15885 l: function() {\r
15886 return {\r
15887 g: 0,\r
15888 c: null,\r
15889 s: "(?:" + utilDate.dayNames.join("|") + ")"\r
15890 };\r
15891 },\r
15892 N: {\r
15893 g: 0,\r
15894 c: null,\r
15895 s: "[1-7]"\r
15896 },\r
15897 // ISO-8601 day number (1 (monday) - 7 (sunday))\r
15898 //<locale type="object" property="parseCodes">\r
15899 S: {\r
15900 g: 0,\r
15901 c: null,\r
15902 s: "(?:st|nd|rd|th)"\r
15903 },\r
15904 //</locale>\r
15905 w: {\r
15906 g: 0,\r
15907 c: null,\r
15908 s: "[0-6]"\r
15909 },\r
15910 // JavaScript day number (0 (sunday) - 6 (saturday))\r
15911 z: {\r
15912 g: 1,\r
15913 c: "z = parseInt(results[{0}], 10);\n",\r
15914 s: "(\\d{1,3})"\r
15915 },\r
15916 // day of the year (0 - 364 (365 in leap years))\r
15917 W: {\r
15918 g: 1,\r
15919 c: "W = parseInt(results[{0}], 10);\n",\r
15920 s: "(\\d{2})"\r
15921 },\r
15922 // ISO-8601 week number (with leading zero)\r
15923 F: function() {\r
15924 return {\r
15925 g: 1,\r
15926 c: "m = parseInt(me.getMonthNumber(results[{0}]), 10);\n",\r
15927 // get localised month number\r
15928 s: "(" + utilDate.monthNames.join("|") + ")"\r
15929 };\r
15930 },\r
15931 M: function() {\r
15932 for (var a = [],\r
15933 i = 0; i < 12; a.push(utilDate.getShortMonthName(i)) , ++i){}\r
15934 // get localised short month names\r
15935 return Ext.applyIf({\r
15936 s: "(" + a.join("|") + ")"\r
15937 }, utilDate.formatCodeToRegex("F"));\r
15938 },\r
15939 m: {\r
15940 g: 1,\r
15941 c: "m = parseInt(results[{0}], 10) - 1;\n",\r
15942 s: "(1[0-2]|0[1-9])"\r
15943 },\r
15944 // month number with leading zeros (01 - 12)\r
15945 n: {\r
15946 g: 1,\r
15947 c: "m = parseInt(results[{0}], 10) - 1;\n",\r
15948 s: "(1[0-2]|[1-9])"\r
15949 },\r
15950 // month number without leading zeros (1 - 12)\r
15951 t: {\r
15952 g: 0,\r
15953 c: null,\r
15954 s: "(?:\\d{2})"\r
15955 },\r
15956 // no. of days in the month (28 - 31)\r
15957 L: {\r
15958 g: 0,\r
15959 c: null,\r
15960 s: "(?:1|0)"\r
15961 },\r
15962 o: {\r
15963 g: 1,\r
15964 c: "y = parseInt(results[{0}], 10);\n",\r
15965 s: "(\\d{4})"\r
15966 },\r
15967 // ISO-8601 year number (with leading zero)\r
15968 Y: {\r
15969 g: 1,\r
15970 c: "y = parseInt(results[{0}], 10);\n",\r
15971 s: "(\\d{4})"\r
15972 },\r
15973 // 4-digit year\r
15974 y: {\r
15975 g: 1,\r
15976 c: "var ty = parseInt(results[{0}], 10);\n" + "y = ty > me.y2kYear ? 1900 + ty : 2000 + ty;\n",\r
15977 // 2-digit year\r
15978 s: "(\\d{2})"\r
15979 },\r
15980 /*
15981 * In the am/pm parsing routines, we allow both upper and lower case
15982 * even though it doesn't exactly match the spec. It gives much more flexibility
15983 * in being able to specify case insensitive regexes.
15984 */\r
15985 //<locale type="object" property="parseCodes">\r
15986 a: {\r
15987 g: 1,\r
15988 c: "if (/(am)/i.test(results[{0}])) {\n" + "if (!h || h == 12) { h = 0; }\n" + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",\r
15989 s: "(am|pm|AM|PM)",\r
15990 calcAtEnd: true\r
15991 },\r
15992 //</locale>\r
15993 //<locale type="object" property="parseCodes">\r
15994 A: {\r
15995 g: 1,\r
15996 c: "if (/(am)/i.test(results[{0}])) {\n" + "if (!h || h == 12) { h = 0; }\n" + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",\r
15997 s: "(AM|PM|am|pm)",\r
15998 calcAtEnd: true\r
15999 },\r
16000 //</locale>\r
16001 g: {\r
16002 g: 1,\r
16003 c: "h = parseInt(results[{0}], 10);\n",\r
16004 s: "(1[0-2]|[0-9])"\r
16005 },\r
16006 // 12-hr format of an hour without leading zeroes (1 - 12)\r
16007 G: {\r
16008 g: 1,\r
16009 c: "h = parseInt(results[{0}], 10);\n",\r
16010 s: "(2[0-3]|1[0-9]|[0-9])"\r
16011 },\r
16012 // 24-hr format of an hour without leading zeroes (0 - 23)\r
16013 h: {\r
16014 g: 1,\r
16015 c: "h = parseInt(results[{0}], 10);\n",\r
16016 s: "(1[0-2]|0[1-9])"\r
16017 },\r
16018 // 12-hr format of an hour with leading zeroes (01 - 12)\r
16019 H: {\r
16020 g: 1,\r
16021 c: "h = parseInt(results[{0}], 10);\n",\r
16022 s: "(2[0-3]|[0-1][0-9])"\r
16023 },\r
16024 // 24-hr format of an hour with leading zeroes (00 - 23)\r
16025 i: {\r
16026 g: 1,\r
16027 c: "i = parseInt(results[{0}], 10);\n",\r
16028 s: "([0-5][0-9])"\r
16029 },\r
16030 // minutes with leading zeros (00 - 59)\r
16031 s: {\r
16032 g: 1,\r
16033 c: "s = parseInt(results[{0}], 10);\n",\r
16034 s: "([0-5][0-9])"\r
16035 },\r
16036 // seconds with leading zeros (00 - 59)\r
16037 u: {\r
16038 g: 1,\r
16039 c: "ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",\r
16040 s: "(\\d+)"\r
16041 },\r
16042 // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)\r
16043 O: {\r
16044 g: 1,\r
16045 c: [\r
16046 "o = results[{0}];",\r
16047 "var sn = o.substring(0,1),",\r
16048 // get + / - sign\r
16049 "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),",\r
16050 // get hours (performs minutes-to-hour conversion also, just in case)\r
16051 "mn = o.substring(3,5) % 60;",\r
16052 // get minutes\r
16053 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"\r
16054 ].// -12hrs <= GMT offset <= 14hrs\r
16055 join("\n"),\r
16056 s: "([+-]\\d{4})"\r
16057 },\r
16058 // GMT offset in hrs and mins\r
16059 P: {\r
16060 g: 1,\r
16061 c: [\r
16062 "o = results[{0}];",\r
16063 "var sn = o.substring(0,1),",\r
16064 // get + / - sign\r
16065 "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),",\r
16066 // get hours (performs minutes-to-hour conversion also, just in case)\r
16067 "mn = o.substring(4,6) % 60;",\r
16068 // get minutes\r
16069 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n"\r
16070 ].// -12hrs <= GMT offset <= 14hrs\r
16071 join("\n"),\r
16072 s: "([+-]\\d{2}:\\d{2})"\r
16073 },\r
16074 // GMT offset in hrs and mins (with colon separator)\r
16075 T: {\r
16076 g: 0,\r
16077 c: null,\r
16078 s: "[A-Z]{1,5}"\r
16079 },\r
16080 // timezone abbrev. may be between 1 - 5 chars\r
16081 Z: {\r
16082 g: 1,\r
16083 c: "zz = results[{0}] * 1;\n" + // -43200 <= UTC offset <= 50400\r
16084 "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",\r
16085 s: "([+-]?\\d{1,5})"\r
16086 },\r
16087 // leading '+' sign is optional for UTC offset\r
16088 c: function() {\r
16089 var calc = [],\r
16090 arr = [\r
16091 utilDate.formatCodeToRegex("Y", 1),\r
16092 // year\r
16093 utilDate.formatCodeToRegex("m", 2),\r
16094 // month\r
16095 utilDate.formatCodeToRegex("d", 3),\r
16096 // day\r
16097 utilDate.formatCodeToRegex("H", 4),\r
16098 // hour\r
16099 utilDate.formatCodeToRegex("i", 5),\r
16100 // minute\r
16101 utilDate.formatCodeToRegex("s", 6),\r
16102 // second\r
16103 {\r
16104 c: "ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"\r
16105 },\r
16106 // decimal fraction of a second (minimum = 1 digit, maximum = unlimited)\r
16107 {\r
16108 c: [\r
16109 // allow either "Z" (i.e. UTC) or "-0530" or "+08:00" (i.e. UTC offset) timezone delimiters. assumes local timezone if no timezone is specified\r
16110 "if(results[8]) {",\r
16111 // timezone specified\r
16112 "if(results[8] == 'Z'){",\r
16113 "zz = 0;",\r
16114 // UTC\r
16115 "}else if (results[8].indexOf(':') > -1){",\r
16116 utilDate.formatCodeToRegex("P", 8).c,\r
16117 // timezone offset with colon separator\r
16118 "}else{",\r
16119 utilDate.formatCodeToRegex("O", 8).c,\r
16120 // timezone offset without colon separator\r
16121 "}",\r
16122 "}"\r
16123 ].join('\n')\r
16124 }\r
16125 ],\r
16126 i, l;\r
16127 for (i = 0 , l = arr.length; i < l; ++i) {\r
16128 calc.push(arr[i].c);\r
16129 }\r
16130 return {\r
16131 g: 1,\r
16132 c: calc.join(""),\r
16133 s: [\r
16134 arr[0].s,\r
16135 // year (required)\r
16136 "(?:",\r
16137 "-",\r
16138 arr[1].s,\r
16139 // month (optional)\r
16140 "(?:",\r
16141 "-",\r
16142 arr[2].s,\r
16143 // day (optional)\r
16144 "(?:",\r
16145 "(?:T| )?",\r
16146 // time delimiter -- either a "T" or a single blank space\r
16147 arr[3].s,\r
16148 ":",\r
16149 arr[4].s,\r
16150 // hour AND minute, delimited by a single colon (optional). MUST be preceded by either a "T" or a single blank space\r
16151 "(?::",\r
16152 arr[5].s,\r
16153 ")?",\r
16154 // seconds (optional)\r
16155 "(?:(?:\\.|,)(\\d+))?",\r
16156 // decimal fraction of a second (e.g. ",12345" or ".98765") (optional)\r
16157 "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?",\r
16158 // "Z" (UTC) or "-0530" (UTC offset without colon delimiter) or "+08:00" (UTC offset with colon delimiter) (optional)\r
16159 ")?",\r
16160 ")?",\r
16161 ")?"\r
16162 ].join("")\r
16163 };\r
16164 },\r
16165 U: {\r
16166 g: 1,\r
16167 c: "u = parseInt(results[{0}], 10);\n",\r
16168 s: "(-?\\d+)"\r
16169 }\r
16170 },\r
16171 // leading minus sign indicates seconds before UNIX epoch\r
16172 //Old Ext.Date prototype methods.\r
16173 /**
16174 * @private
16175 */\r
16176 dateFormat: function(date, format) {\r
16177 return utilDate.format(date, format);\r
16178 },\r
16179 /**
16180 * Compares if two dates are equal by comparing their values.
16181 * @param {Date} date1
16182 * @param {Date} date2
16183 * @return {Boolean} `true` if the date values are equal
16184 */\r
16185 isEqual: function(date1, date2) {\r
16186 // check we have 2 date objects\r
16187 if (date1 && date2) {\r
16188 return (date1.getTime() === date2.getTime());\r
16189 }\r
16190 // one or both isn't a date, only equal if both are falsey\r
16191 return !(date1 || date2);\r
16192 },\r
16193 /**
16194 * Formats a date given the supplied format string.
16195 * @param {Date} date The date to format
16196 * @param {String} format The format string
16197 * @return {String} The formatted date or an empty string if date parameter is not a JavaScript Date object
16198 */\r
16199 format: function(date, format) {\r
16200 var formatFunctions = utilDate.formatFunctions;\r
16201 if (!Ext.isDate(date)) {\r
16202 return '';\r
16203 }\r
16204 if (formatFunctions[format] == null) {\r
16205 utilDate.createFormat(format);\r
16206 }\r
16207 return formatFunctions[format].call(date) + '';\r
16208 },\r
16209 /**
16210 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
16211 *
16212 * __Note:__ The date string returned by the JavaScript Date object's `toString()` method varies
16213 * between browsers (e.g. FF vs IE) and system region settings (e.g. IE in Asia vs IE in America).
16214 * For a given date string e.g. "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)",
16215 * `getTimezone()` first tries to get the timezone abbreviation from between a pair of parentheses
16216 * (which may or may not be present), failing which it proceeds to get the timezone abbreviation
16217 * from the GMT offset portion of the date string.
16218 *
16219 * @example
16220 * var dt = new Date('9/17/2011');
16221 * console.log(Ext.Date.getTimezone(dt));
16222 *
16223 * @param {Date} date The date
16224 * @return {String} The abbreviated timezone name (e.g. 'CST', 'PDT', 'EDT', 'MPST' ...).
16225 */\r
16226 getTimezone: function(date) {\r
16227 // the following list shows the differences between date strings from different browsers on a WinXP SP2 machine from an Asian locale:\r
16228 //\r
16229 // Opera : "Thu, 25 Oct 2007 22:53:45 GMT+0800" -- shortest (weirdest) date string of the lot\r
16230 // Safari : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone (same as FF)\r
16231 // FF : "Thu Oct 25 2007 22:55:35 GMT+0800 (Malay Peninsula Standard Time)" -- value in parentheses always gives the correct timezone\r
16232 // IE : "Thu Oct 25 22:54:35 UTC+0800 2007" -- (Asian system setting) look for 3-4 letter timezone abbrev\r
16233 // IE : "Thu Oct 25 17:06:37 PDT 2007" -- (American system setting) look for 3-4 letter timezone abbrev\r
16234 //\r
16235 // this crazy regex attempts to guess the correct timezone abbreviation despite these differences.\r
16236 // step 1: (?:\((.*)\) -- find timezone in parentheses\r
16237 // step 2: ([A-Z]{1,4})(?:[\-+][0-9]{4})?(?: -?\d+)?) -- if nothing was found in step 1, find timezone from timezone offset portion of date string\r
16238 // step 3: remove all non uppercase characters found in step 1 and 2\r
16239 return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,5})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");\r
16240 },\r
16241 /**
16242 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
16243 *
16244 * @example
16245 * var dt = new Date('9/17/2011');
16246 * console.log(Ext.Date.getGMTOffset(dt));
16247 *
16248 * @param {Date} date The date
16249 * @param {Boolean} [colon=false] `true` to separate the hours and minutes with a colon.
16250 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600').
16251 */\r
16252 getGMTOffset: function(date, colon) {\r
16253 var offset = date.getTimezoneOffset();\r
16254 return (offset > 0 ? "-" : "+") + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0") + (colon ? ":" : "") + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");\r
16255 },\r
16256 /**
16257 * Get the numeric day number of the year, adjusted for leap year.
16258 *
16259 * @example
16260 * var dt = new Date('9/17/2011');
16261 * console.log(Ext.Date.getDayOfYear(dt)); // 259
16262 *
16263 * @param {Date} date The date
16264 * @return {Number} 0 to 364 (365 in leap years).
16265 */\r
16266 getDayOfYear: function(date) {\r
16267 var num = 0,\r
16268 d = utilDate.clone(date),\r
16269 m = date.getMonth(),\r
16270 i;\r
16271 for (i = 0 , d.setDate(1) , d.setMonth(0); i < m; d.setMonth(++i)) {\r
16272 num += utilDate.getDaysInMonth(d);\r
16273 }\r
16274 return num + date.getDate() - 1;\r
16275 },\r
16276 /**
16277 * Get the numeric ISO-8601 week number of the year.
16278 * (equivalent to the format specifier 'W', but without a leading zero).
16279 *
16280 * @example
16281 * var dt = new Date('9/17/2011');
16282 * console.log(Ext.Date.getWeekOfYear(dt)); // 37
16283 *
16284 * @param {Date} date The date.
16285 * @return {Number} 1 to 53.
16286 * @method
16287 */\r
16288 getWeekOfYear: (function() {\r
16289 // adapted from http://www.merlyn.demon.co.uk/weekcalc.htm\r
16290 var ms1d = 86400000,\r
16291 // milliseconds in a day\r
16292 ms7d = 7 * ms1d;\r
16293 // milliseconds in a week\r
16294 return function(date) {\r
16295 // return a closure so constants get calculated only once\r
16296 var DC3 = nativeDate.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d,\r
16297 // an Absolute Day Number\r
16298 AWN = Math.floor(DC3 / 7),\r
16299 // an Absolute Week Number\r
16300 Wyr = new nativeDate(AWN * ms7d).getUTCFullYear();\r
16301 return AWN - Math.floor(nativeDate.UTC(Wyr, 0, 7) / ms7d) + 1;\r
16302 };\r
16303 }()),\r
16304 /**
16305 * Checks if the current date falls within a leap year.
16306 *
16307 * @example
16308 * var dt = new Date('1/10/2011');
16309 * console.log(Ext.Date.isLeapYear(dt)); // false
16310 *
16311 * @param {Date} date The date
16312 * @return {Boolean} `true` if the current date falls within a leap year, `false` otherwise.
16313 */\r
16314 isLeapYear: function(date) {\r
16315 var year = date.getFullYear();\r
16316 return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));\r
16317 },\r
16318 /**
16319 * Get the first day of the current month, adjusted for leap year. The returned value
16320 * is the numeric day index within the week (0-6) which can be used in conjunction with
16321 * the {@link #monthNames} array to retrieve the textual day name.
16322 *
16323 * @example
16324 * var dt = new Date('1/10/2007'),
16325 * firstDay = Ext.Date.getFirstDayOfMonth(dt);
16326 * console.log(Ext.Date.dayNames[firstDay]); // output: 'Monday'
16327 *
16328 * @param {Date} date The date
16329 * @return {Number} The day number (0-6).
16330 */\r
16331 getFirstDayOfMonth: function(date) {\r
16332 var day = (date.getDay() - (date.getDate() - 1)) % 7;\r
16333 return (day < 0) ? (day + 7) : day;\r
16334 },\r
16335 /**
16336 * Get the last day of the current month, adjusted for leap year. The returned value
16337 * is the numeric day index within the week (0-6) which can be used in conjunction with
16338 * the {@link #monthNames} array to retrieve the textual day name.
16339 *
16340 * @example
16341 * var dt = new Date('1/10/2007'),
16342 * lastDay = Ext.Date.getLastDayOfMonth(dt);
16343 *
16344 * console.log(Ext.Date.dayNames[lastDay]); // output: 'Wednesday'
16345 *
16346 * @param {Date} date The date
16347 * @return {Number} The day number (0-6).
16348 */\r
16349 getLastDayOfMonth: function(date) {\r
16350 return utilDate.getLastDateOfMonth(date).getDay();\r
16351 },\r
16352 /**
16353 * Get the date of the first day of the month in which this date resides.
16354 * @param {Date} date The date
16355 * @return {Date}
16356 */\r
16357 getFirstDateOfMonth: function(date) {\r
16358 return new nativeDate(date.getFullYear(), date.getMonth(), 1);\r
16359 },\r
16360 /**
16361 * Get the date of the last day of the month in which this date resides.
16362 * @param {Date} date The date
16363 * @return {Date}
16364 */\r
16365 getLastDateOfMonth: function(date) {\r
16366 return new nativeDate(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));\r
16367 },\r
16368 /**
16369 * Get the number of days in the current month, adjusted for leap year.
16370 * @param {Date} date The date
16371 * @return {Number} The number of days in the month.
16372 * @method
16373 */\r
16374 getDaysInMonth: (function() {\r
16375 var daysInMonth = [\r
16376 31,\r
16377 28,\r
16378 31,\r
16379 30,\r
16380 31,\r
16381 30,\r
16382 31,\r
16383 31,\r
16384 30,\r
16385 31,\r
16386 30,\r
16387 31\r
16388 ];\r
16389 return function(date) {\r
16390 // return a closure for efficiency\r
16391 var m = date.getMonth();\r
16392 return m === 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];\r
16393 };\r
16394 }()),\r
16395 //<locale type="function">\r
16396 /**
16397 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
16398 * @param {Date} date The date
16399 * @return {String} 'st, 'nd', 'rd' or 'th'.
16400 */\r
16401 getSuffix: function(date) {\r
16402 switch (date.getDate()) {\r
16403 case 1:\r
16404 case 21:\r
16405 case 31:\r
16406 return "st";\r
16407 case 2:\r
16408 case 22:\r
16409 return "nd";\r
16410 case 3:\r
16411 case 23:\r
16412 return "rd";\r
16413 default:\r
16414 return "th";\r
16415 }\r
16416 },\r
16417 //</locale>\r
16418 /**
16419 * Creates and returns a new Date instance with the exact same date value as the called instance.
16420 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
16421 * variable will also be changed. When the intention is to create a new variable that will not
16422 * modify the original instance, you should create a clone.
16423 *
16424 * Example of correctly cloning a date:
16425 *
16426 * //wrong way:
16427 * var orig = new Date('10/1/2006');
16428 * var copy = orig;
16429 * copy.setDate(5);
16430 * console.log(orig); // returns 'Thu Oct 05 2006'!
16431 *
16432 * //correct way:
16433 * var orig = new Date('10/1/2006'),
16434 * copy = Ext.Date.clone(orig);
16435 * copy.setDate(5);
16436 * console.log(orig); // returns 'Thu Oct 01 2006'
16437 *
16438 * @param {Date} date The date.
16439 * @return {Date} The new Date instance.
16440 */\r
16441 clone: function(date) {\r
16442 return new nativeDate(date.getTime());\r
16443 },\r
16444 /**
16445 * Checks if the current date is affected by Daylight Saving Time (DST).
16446 * @param {Date} date The date
16447 * @return {Boolean} `true` if the current date is affected by DST.
16448 */\r
16449 isDST: function(date) {\r
16450 // adapted from http://sencha.com/forum/showthread.php?p=247172#post247172\r
16451 // courtesy of @geoffrey.mcgill\r
16452 return new nativeDate(date.getFullYear(), 0, 1).getTimezoneOffset() !== date.getTimezoneOffset();\r
16453 },\r
16454 /**
16455 * Attempts to clear all time information from this Date by setting the time to midnight of the same day,
16456 * automatically adjusting for Daylight Saving Time (DST) where applicable.
16457 *
16458 * __Note:__ DST timezone information for the browser's host operating system is assumed to be up-to-date.
16459 * @param {Date} date The date
16460 * @param {Boolean} [clone=false] `true` to create a clone of this date, clear the time and return it.
16461 * @return {Date} this or the clone.
16462 */\r
16463 clearTime: function(date, clone) {\r
16464 // handles invalid dates preventing the browser from crashing.\r
16465 if (isNaN(date.getTime())) {\r
16466 return date;\r
16467 }\r
16468 if (clone) {\r
16469 return utilDate.clearTime(utilDate.clone(date));\r
16470 }\r
16471 // get current date before clearing time\r
16472 var d = date.getDate(),\r
16473 hr, c;\r
16474 // clear time\r
16475 date.setHours(0);\r
16476 date.setMinutes(0);\r
16477 date.setSeconds(0);\r
16478 date.setMilliseconds(0);\r
16479 if (date.getDate() !== d) {\r
16480 // account for DST (i.e. day of month changed when setting hour = 0)\r
16481 // note: DST adjustments are assumed to occur in multiples of 1 hour (this is almost always the case)\r
16482 // refer to http://www.timeanddate.com/time/aboutdst.html for the (rare) exceptions to this rule\r
16483 // increment hour until cloned date == current date\r
16484 for (hr = 1 , c = utilDate.add(date, utilDate.HOUR, hr); c.getDate() !== d; hr++ , c = utilDate.add(date, utilDate.HOUR, hr)){}\r
16485 date.setDate(d);\r
16486 date.setHours(c.getHours());\r
16487 }\r
16488 return date;\r
16489 },\r
16490 /**
16491 * Provides a convenient method for performing basic date arithmetic. This method
16492 * does not modify the Date instance being called - it creates and returns
16493 * a new Date instance containing the resulting date value.
16494 *
16495 * Examples:
16496 *
16497 * // Basic usage:
16498 * var dt = Ext.Date.add(new Date('10/29/2006'), Ext.Date.DAY, 5);
16499 * console.log(dt); // returns 'Fri Nov 03 2006 00:00:00'
16500 *
16501 * // Negative values will be subtracted:
16502 * var dt2 = Ext.Date.add(new Date('10/1/2006'), Ext.Date.DAY, -5);
16503 * console.log(dt2); // returns 'Tue Sep 26 2006 00:00:00'
16504 *
16505 * // Decimal values can be used:
16506 * var dt3 = Ext.Date.add(new Date('10/1/2006'), Ext.Date.DAY, 1.25);
16507 * console.log(dt3); // returns 'Mon Oct 02 2006 06:00:00'
16508 *
16509 * @param {Date} date The date to modify
16510 * @param {String} interval A valid date interval enum value.
16511 * @param {Number} value The amount to add to the current date.
16512 * @return {Date} The new Date instance.
16513 */\r
16514 add: function(date, interval, value) {\r
16515 var d = utilDate.clone(date),\r
16516 day, decimalValue,\r
16517 base = 0;\r
16518 if (!interval || value === 0) {\r
16519 return d;\r
16520 }\r
16521 decimalValue = value - parseInt(value, 10);\r
16522 value = parseInt(value, 10);\r
16523 if (value) {\r
16524 switch (interval.toLowerCase()) {\r
16525 // See EXTJSIV-7418. We use setTime() here to deal with issues related to\r
16526 // the switchover that occurs when changing to daylight savings and vice\r
16527 // versa. setTime() handles this correctly where setHour/Minute/Second/Millisecond\r
16528 // do not. Let's assume the DST change occurs at 2am and we're incrementing using add\r
16529 // for 15 minutes at time. When entering DST, we should see:\r
16530 // 01:30am\r
16531 // 01:45am\r
16532 // 03:00am // skip 2am because the hour does not exist\r
16533 // ...\r
16534 // Similarly, leaving DST, we should see:\r
16535 // 01:30am\r
16536 // 01:45am\r
16537 // 01:00am // repeat 1am because that's the change over\r
16538 // 01:30am\r
16539 // 01:45am\r
16540 // 02:00am\r
16541 // ....\r
16542 // \r
16543 case utilDate.MILLI:\r
16544 d.setTime(d.getTime() + value);\r
16545 break;\r
16546 case utilDate.SECOND:\r
16547 d.setTime(d.getTime() + value * 1000);\r
16548 break;\r
16549 case utilDate.MINUTE:\r
16550 d.setTime(d.getTime() + value * 60 * 1000);\r
16551 break;\r
16552 case utilDate.HOUR:\r
16553 d.setTime(d.getTime() + value * 60 * 60 * 1000);\r
16554 break;\r
16555 case utilDate.DAY:\r
16556 d.setDate(d.getDate() + value);\r
16557 break;\r
16558 case utilDate.MONTH:\r
16559 day = date.getDate();\r
16560 if (day > 28) {\r
16561 day = Math.min(day, utilDate.getLastDateOfMonth(utilDate.add(utilDate.getFirstDateOfMonth(date), utilDate.MONTH, value)).getDate());\r
16562 };\r
16563 d.setDate(day);\r
16564 d.setMonth(date.getMonth() + value);\r
16565 break;\r
16566 case utilDate.YEAR:\r
16567 day = date.getDate();\r
16568 if (day > 28) {\r
16569 day = Math.min(day, utilDate.getLastDateOfMonth(utilDate.add(utilDate.getFirstDateOfMonth(date), utilDate.YEAR, value)).getDate());\r
16570 };\r
16571 d.setDate(day);\r
16572 d.setFullYear(date.getFullYear() + value);\r
16573 break;\r
16574 }\r
16575 }\r
16576 if (decimalValue) {\r
16577 switch (interval.toLowerCase()) {\r
16578 case utilDate.MILLI:\r
16579 base = 1;\r
16580 break;\r
16581 case utilDate.SECOND:\r
16582 base = 1000;\r
16583 break;\r
16584 case utilDate.MINUTE:\r
16585 base = 1000 * 60;\r
16586 break;\r
16587 case utilDate.HOUR:\r
16588 base = 1000 * 60 * 60;\r
16589 break;\r
16590 case utilDate.DAY:\r
16591 base = 1000 * 60 * 60 * 24;\r
16592 break;\r
16593 case utilDate.MONTH:\r
16594 day = utilDate.getDaysInMonth(d);\r
16595 base = 1000 * 60 * 60 * 24 * day;\r
16596 break;\r
16597 case utilDate.YEAR:\r
16598 day = (utilDate.isLeapYear(d) ? 366 : 365);\r
16599 base = 1000 * 60 * 60 * 24 * day;\r
16600 break;\r
16601 }\r
16602 if (base) {\r
16603 d.setTime(d.getTime() + base * decimalValue);\r
16604 }\r
16605 }\r
16606 return d;\r
16607 },\r
16608 /**
16609 * Provides a convenient method for performing basic date arithmetic. This method
16610 * does not modify the Date instance being called - it creates and returns
16611 * a new Date instance containing the resulting date value.
16612 *
16613 * Examples:
16614 *
16615 * // Basic usage:
16616 * var dt = Ext.Date.subtract(new Date('10/29/2006'), Ext.Date.DAY, 5);
16617 * console.log(dt); // returns 'Tue Oct 24 2006 00:00:00'
16618 *
16619 * // Negative values will be added:
16620 * var dt2 = Ext.Date.subtract(new Date('10/1/2006'), Ext.Date.DAY, -5);
16621 * console.log(dt2); // returns 'Fri Oct 6 2006 00:00:00'
16622 *
16623 * // Decimal values can be used:
16624 * var dt3 = Ext.Date.subtract(new Date('10/1/2006'), Ext.Date.DAY, 1.25);
16625 * console.log(dt3); // returns 'Fri Sep 29 2006 06:00:00'
16626 *
16627 * @param {Date} date The date to modify
16628 * @param {String} interval A valid date interval enum value.
16629 * @param {Number} value The amount to subtract from the current date.
16630 * @return {Date} The new Date instance.
16631 */\r
16632 subtract: function(date, interval, value) {\r
16633 return utilDate.add(date, interval, -value);\r
16634 },\r
16635 /**
16636 * Checks if a date falls on or between the given start and end dates.
16637 * @param {Date} date The date to check
16638 * @param {Date} start Start date
16639 * @param {Date} end End date
16640 * @return {Boolean} `true` if this date falls on or between the given start and end dates.
16641 */\r
16642 between: function(date, start, end) {\r
16643 var t = date.getTime();\r
16644 return start.getTime() <= t && t <= end.getTime();\r
16645 },\r
16646 //Maintains compatibility with old static and prototype window.Date methods.\r
16647 compat: function() {\r
16648 var p,\r
16649 statics = [\r
16650 'useStrict',\r
16651 'formatCodeToRegex',\r
16652 'parseFunctions',\r
16653 'parseRegexes',\r
16654 'formatFunctions',\r
16655 'y2kYear',\r
16656 'MILLI',\r
16657 'SECOND',\r
16658 'MINUTE',\r
16659 'HOUR',\r
16660 'DAY',\r
16661 'MONTH',\r
16662 'YEAR',\r
16663 'defaults',\r
16664 'dayNames',\r
16665 'monthNames',\r
16666 'monthNumbers',\r
16667 'getShortMonthName',\r
16668 'getShortDayName',\r
16669 'getMonthNumber',\r
16670 'formatCodes',\r
16671 'isValid',\r
16672 'parseDate',\r
16673 'getFormatCode',\r
16674 'createFormat',\r
16675 'createParser',\r
16676 'parseCodes'\r
16677 ],\r
16678 proto = [\r
16679 'dateFormat',\r
16680 'format',\r
16681 'getTimezone',\r
16682 'getGMTOffset',\r
16683 'getDayOfYear',\r
16684 'getWeekOfYear',\r
16685 'isLeapYear',\r
16686 'getFirstDayOfMonth',\r
16687 'getLastDayOfMonth',\r
16688 'getDaysInMonth',\r
16689 'getSuffix',\r
16690 'clone',\r
16691 'isDST',\r
16692 'clearTime',\r
16693 'add',\r
16694 'between'\r
16695 ],\r
16696 sLen = statics.length,\r
16697 pLen = proto.length,\r
16698 stat, prot, s;\r
16699 //Append statics\r
16700 for (s = 0; s < sLen; s++) {\r
16701 stat = statics[s];\r
16702 nativeDate[stat] = utilDate[stat];\r
16703 }\r
16704 //Append to prototype\r
16705 for (p = 0; p < pLen; p++) {\r
16706 prot = proto[p];\r
16707 nativeDate.prototype[prot] = function() {\r
16708 var args = Array.prototype.slice.call(arguments);\r
16709 args.unshift(this);\r
16710 return utilDate[prot].apply(utilDate, args);\r
16711 };\r
16712 }\r
16713 },\r
16714 /**
16715 * Calculate how many units are there between two time.
16716 * @param {Date} min The first time.
16717 * @param {Date} max The second time.
16718 * @param {String} unit The unit. This unit is compatible with the date interval constants.
16719 * @return {Number} The maximum number n of units that min + n * unit <= max.
16720 */\r
16721 diff: function(min, max, unit) {\r
16722 var est,\r
16723 diff = +max - min;\r
16724 switch (unit) {\r
16725 case utilDate.MILLI:\r
16726 return diff;\r
16727 case utilDate.SECOND:\r
16728 return Math.floor(diff / 1000);\r
16729 case utilDate.MINUTE:\r
16730 return Math.floor(diff / 60000);\r
16731 case utilDate.HOUR:\r
16732 return Math.floor(diff / 3600000);\r
16733 case utilDate.DAY:\r
16734 return Math.floor(diff / 86400000);\r
16735 case 'w':\r
16736 return Math.floor(diff / 604800000);\r
16737 case utilDate.MONTH:\r
16738 est = (max.getFullYear() * 12 + max.getMonth()) - (min.getFullYear() * 12 + min.getMonth());\r
16739 if (utilDate.add(min, unit, est) > max) {\r
16740 return est - 1;\r
16741 };\r
16742 return est;\r
16743 case utilDate.YEAR:\r
16744 est = max.getFullYear() - min.getFullYear();\r
16745 if (utilDate.add(min, unit, est) > max) {\r
16746 return est - 1;\r
16747 } else {\r
16748 return est;\r
16749 };\r
16750 }\r
16751 },\r
16752 /**
16753 * Align the date to `unit`.
16754 * @param {Date} date The date to be aligned.
16755 * @param {String} unit The unit. This unit is compatible with the date interval constants.
16756 * @return {Date} The aligned date.
16757 */\r
16758 align: function(date, unit, step) {\r
16759 var num = new nativeDate(+date);\r
16760 switch (unit.toLowerCase()) {\r
16761 case utilDate.MILLI:\r
16762 return num;\r
16763 case utilDate.SECOND:\r
16764 num.setUTCSeconds(num.getUTCSeconds() - num.getUTCSeconds() % step);\r
16765 num.setUTCMilliseconds(0);\r
16766 return num;\r
16767 case utilDate.MINUTE:\r
16768 num.setUTCMinutes(num.getUTCMinutes() - num.getUTCMinutes() % step);\r
16769 num.setUTCSeconds(0);\r
16770 num.setUTCMilliseconds(0);\r
16771 return num;\r
16772 case utilDate.HOUR:\r
16773 num.setUTCHours(num.getUTCHours() - num.getUTCHours() % step);\r
16774 num.setUTCMinutes(0);\r
16775 num.setUTCSeconds(0);\r
16776 num.setUTCMilliseconds(0);\r
16777 return num;\r
16778 case utilDate.DAY:\r
16779 if (step === 7 || step === 14) {\r
16780 num.setUTCDate(num.getUTCDate() - num.getUTCDay() + 1);\r
16781 };\r
16782 num.setUTCHours(0);\r
16783 num.setUTCMinutes(0);\r
16784 num.setUTCSeconds(0);\r
16785 num.setUTCMilliseconds(0);\r
16786 return num;\r
16787 case utilDate.MONTH:\r
16788 num.setUTCMonth(num.getUTCMonth() - (num.getUTCMonth() - 1) % step, 1);\r
16789 num.setUTCHours(0);\r
16790 num.setUTCMinutes(0);\r
16791 num.setUTCSeconds(0);\r
16792 num.setUTCMilliseconds(0);\r
16793 return num;\r
16794 case utilDate.YEAR:\r
16795 num.setUTCFullYear(num.getUTCFullYear() - num.getUTCFullYear() % step, 1, 1);\r
16796 num.setUTCHours(0);\r
16797 num.setUTCMinutes(0);\r
16798 num.setUTCSeconds(0);\r
16799 num.setUTCMilliseconds(0);\r
16800 return date;\r
16801 }\r
16802 }\r
16803 };\r
16804}());\r
16805\r
16806/**
16807 * @class Ext.Function
16808 *
16809 * A collection of useful static methods to deal with function callbacks.
16810 * @singleton
16811 */\r
16812Ext.Function = (function() {\r
16813 // @define Ext.lang.Function\r
16814 // @define Ext.Function\r
16815 // @require Ext\r
16816 // @require Ext.lang.Array\r
16817 var lastTime = 0,\r
16818 animFrameId,\r
16819 animFrameHandlers = [],\r
16820 animFrameNoArgs = [],\r
16821 idSource = 0,\r
16822 animFrameMap = {},\r
16823 win = window,\r
16824 global = Ext.global,\r
16825 hasImmediate = !!(global.setImmediate && global.clearImmediate),\r
16826 requestAnimFrame = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || function(callback) {\r
16827 var currTime = Ext.now(),\r
16828 timeToCall = Math.max(0, 16 - (currTime - lastTime)),\r
16829 id = win.setTimeout(function() {\r
16830 callback(currTime + timeToCall);\r
16831 }, timeToCall);\r
16832 lastTime = currTime + timeToCall;\r
16833 return id;\r
16834 },\r
16835 fireHandlers = function() {\r
16836 var len = animFrameHandlers.length,\r
16837 id, i, handler;\r
16838 animFrameId = null;\r
16839 // Fire all animation frame handlers in one go\r
16840 for (i = 0; i < len; i++) {\r
16841 handler = animFrameHandlers[i];\r
16842 id = handler[3];\r
16843 // Check if this timer has been canceled; its map entry is going to be removed\r
16844 if (animFrameMap[id]) {\r
16845 handler[0].apply(handler[1] || global, handler[2] || animFrameNoArgs);\r
16846 delete animFrameMap[id];\r
16847 }\r
16848 }\r
16849 // Clear all fired animation frame handlers, don't forget that new handlers\r
16850 // could have been created in user handler functions called in the loop above\r
16851 animFrameHandlers = animFrameHandlers.slice(len);\r
16852 },\r
16853 fireElevatedHandlers = function() {\r
16854 Ext.elevateFunction(fireHandlers);\r
16855 },\r
16856 ExtFunction = {\r
16857 /**
16858 * A very commonly used method throughout the framework. It acts as a wrapper around another method
16859 * which originally accepts 2 arguments for `name` and `value`.
16860 * The wrapped function then allows "flexible" value setting of either:
16861 *
16862 * - `name` and `value` as 2 arguments
16863 * - one single object argument with multiple key - value pairs
16864 *
16865 * For example:
16866 *
16867 * var setValue = Ext.Function.flexSetter(function(name, value) {
16868 * this[name] = value;
16869 * });
16870 *
16871 * // Afterwards
16872 * // Setting a single name - value
16873 * setValue('name1', 'value1');
16874 *
16875 * // Settings multiple name - value pairs
16876 * setValue({
16877 * name1: 'value1',
16878 * name2: 'value2',
16879 * name3: 'value3'
16880 * });
16881 *
16882 * @param {Function} setter The single value setter method.
16883 * @param {String} setter.name The name of the value being set.
16884 * @param {Object} setter.value The value being set.
16885 * @return {Function}
16886 */\r
16887 flexSetter: function(setter) {\r
16888 return function(name, value) {\r
16889 var k, i;\r
16890 if (name !== null) {\r
16891 if (typeof name !== 'string') {\r
16892 for (k in name) {\r
16893 if (name.hasOwnProperty(k)) {\r
16894 setter.call(this, k, name[k]);\r
16895 }\r
16896 }\r
16897 if (Ext.enumerables) {\r
16898 for (i = Ext.enumerables.length; i--; ) {\r
16899 k = Ext.enumerables[i];\r
16900 if (name.hasOwnProperty(k)) {\r
16901 setter.call(this, k, name[k]);\r
16902 }\r
16903 }\r
16904 }\r
16905 } else {\r
16906 setter.call(this, name, value);\r
16907 }\r
16908 }\r
16909 return this;\r
16910 };\r
16911 },\r
16912 /**
16913 * Create a new function from the provided `fn`, change `this` to the provided scope,
16914 * optionally overrides arguments for the call. Defaults to the arguments passed by
16915 * the caller.
16916 *
16917 * {@link Ext#bind Ext.bind} is alias for {@link Ext.Function#bind Ext.Function.bind}
16918 *
16919 * **NOTE:** This method is deprecated. Use the standard `bind` method of JavaScript
16920 * `Function` instead:
16921 *
16922 * function foo () {
16923 * ...
16924 * }
16925 *
16926 * var fn = foo.bind(this);
16927 *
16928 * This method is unavailable natively on IE8 and IE/Quirks but Ext JS provides a
16929 * "polyfill" to emulate the important features of the standard `bind` method. In
16930 * particular, the polyfill only provides binding of "this" and optional arguments.
16931 *
16932 * @param {Function} fn The function to delegate.
16933 * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
16934 * **If omitted, defaults to the default global environment object (usually the browser window).**
16935 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
16936 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
16937 * if a number the args are inserted at the specified position.
16938 * @return {Function} The new function.
16939 */\r
16940 bind: function(fn, scope, args, appendArgs) {\r
16941 if (arguments.length === 2) {\r
16942 return function() {\r
16943 return fn.apply(scope, arguments);\r
16944 };\r
16945 }\r
16946 var method = fn,\r
16947 slice = Array.prototype.slice;\r
16948 return function() {\r
16949 var callArgs = args || arguments;\r
16950 if (appendArgs === true) {\r
16951 callArgs = slice.call(arguments, 0);\r
16952 callArgs = callArgs.concat(args);\r
16953 } else if (typeof appendArgs === 'number') {\r
16954 callArgs = slice.call(arguments, 0);\r
16955 // copy arguments first\r
16956 Ext.Array.insert(callArgs, appendArgs, args);\r
16957 }\r
16958 return method.apply(scope || global, callArgs);\r
16959 };\r
16960 },\r
16961 /**
16962 * Captures the given parameters for a later call to `Ext.callback`. This binding is
16963 * most useful for resolving scopes for example to an `Ext.app.ViewController`.
16964 *
16965 * The arguments match that of `Ext.callback` except for the `args` which, if provided
16966 * to this method, are prepended to any arguments supplied by the eventual caller of
16967 * the returned function.
16968 *
16969 * @return {Function} A function that, when called, uses `Ext.callback` to call the
16970 * captured `callback`.
16971 * @since 5.0.0
16972 */\r
16973 bindCallback: function(callback, scope, args, delay, caller) {\r
16974 return function() {\r
16975 var a = Ext.Array.slice(arguments);\r
16976 return Ext.callback(callback, scope, args ? args.concat(a) : a, delay, caller);\r
16977 };\r
16978 },\r
16979 /**
16980 * Create a new function from the provided `fn`, the arguments of which are pre-set to `args`.
16981 * New arguments passed to the newly created callback when it's invoked are appended after the pre-set ones.
16982 * This is especially useful when creating callbacks.
16983 *
16984 * For example:
16985 *
16986 * var originalFunction = function(){
16987 * alert(Ext.Array.from(arguments).join(' '));
16988 * };
16989 *
16990 * var callback = Ext.Function.pass(originalFunction, ['Hello', 'World']);
16991 *
16992 * callback(); // alerts 'Hello World'
16993 * callback('by Me'); // alerts 'Hello World by Me'
16994 *
16995 * {@link Ext#pass Ext.pass} is alias for {@link Ext.Function#pass Ext.Function.pass}
16996 *
16997 * @param {Function} fn The original function.
16998 * @param {Array} args The arguments to pass to new callback.
16999 * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
17000 * @return {Function} The new callback function.
17001 */\r
17002 pass: function(fn, args, scope) {\r
17003 if (!Ext.isArray(args)) {\r
17004 if (Ext.isIterable(args)) {\r
17005 args = Ext.Array.clone(args);\r
17006 } else {\r
17007 args = args !== undefined ? [\r
17008 args\r
17009 ] : [];\r
17010 }\r
17011 }\r
17012 return function() {\r
17013 var fnArgs = args.slice();\r
17014 fnArgs.push.apply(fnArgs, arguments);\r
17015 return fn.apply(scope || this, fnArgs);\r
17016 };\r
17017 },\r
17018 /**
17019 * Create an alias to the provided method property with name `methodName` of `object`.
17020 * Note that the execution scope will still be bound to the provided `object` itself.
17021 *
17022 * @param {Object/Function} object
17023 * @param {String} methodName
17024 * @return {Function} aliasFn
17025 */\r
17026 alias: function(object, methodName) {\r
17027 return function() {\r
17028 return object[methodName].apply(object, arguments);\r
17029 };\r
17030 },\r
17031 /**
17032 * Create a "clone" of the provided method. The returned method will call the given
17033 * method passing along all arguments and the "this" pointer and return its result.
17034 *
17035 * @param {Function} method
17036 * @return {Function} cloneFn
17037 */\r
17038 clone: function(method) {\r
17039 return function() {\r
17040 return method.apply(this, arguments);\r
17041 };\r
17042 },\r
17043 /**
17044 * Creates an interceptor function. The passed function is called before the original one. If it returns false,
17045 * the original one is not called. The resulting function returns the results of the original function.
17046 * The passed function is called with the parameters of the original function. Example usage:
17047 *
17048 * var sayHi = function(name){
17049 * alert('Hi, ' + name);
17050 * };
17051 *
17052 * sayHi('Fred'); // alerts "Hi, Fred"
17053 *
17054 * // create a new function that validates input without
17055 * // directly modifying the original function:
17056 * var sayHiToFriend = Ext.Function.createInterceptor(sayHi, function(name){
17057 * return name === 'Brian';
17058 * });
17059 *
17060 * sayHiToFriend('Fred'); // no alert
17061 * sayHiToFriend('Brian'); // alerts "Hi, Brian"
17062 *
17063 * @param {Function} origFn The original function.
17064 * @param {Function} newFn The function to call before the original.
17065 * @param {Object} [scope] The scope (`this` reference) in which the passed function is executed.
17066 * **If omitted, defaults to the scope in which the original function is called or the browser window.**
17067 * @param {Object} [returnValue=null] The value to return if the passed function return `false`.
17068 * @return {Function} The new function.
17069 */\r
17070 createInterceptor: function(origFn, newFn, scope, returnValue) {\r
17071 if (!Ext.isFunction(newFn)) {\r
17072 return origFn;\r
17073 } else {\r
17074 returnValue = Ext.isDefined(returnValue) ? returnValue : null;\r
17075 return function() {\r
17076 var me = this,\r
17077 args = arguments;\r
17078 return (newFn.apply(scope || me || global, args) !== false) ? origFn.apply(me || global, args) : returnValue;\r
17079 };\r
17080 }\r
17081 },\r
17082 /**
17083 * Creates a delegate (callback) which, when called, executes after a specific delay.
17084 *
17085 * @param {Function} fn The function which will be called on a delay when the returned function is called.
17086 * Optionally, a replacement (or additional) argument list may be specified.
17087 * @param {Number} delay The number of milliseconds to defer execution by whenever called.
17088 * @param {Object} scope (optional) The scope (`this` reference) used by the function at execution time.
17089 * @param {Array} args (optional) Override arguments for the call. (Defaults to the arguments passed by the caller)
17090 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
17091 * if a number the args are inserted at the specified position.
17092 * @return {Function} A function which, when called, executes the original function after the specified delay.
17093 */\r
17094 createDelayed: function(fn, delay, scope, args, appendArgs) {\r
17095 if (scope || args) {\r
17096 fn = Ext.Function.bind(fn, scope, args, appendArgs);\r
17097 }\r
17098 return function() {\r
17099 var me = this,\r
17100 args = Array.prototype.slice.call(arguments);\r
17101 setTimeout(function() {\r
17102 if (Ext.elevateFunction) {\r
17103 Ext.elevateFunction(fn, me, args);\r
17104 } else {\r
17105 fn.apply(me, args);\r
17106 }\r
17107 }, delay);\r
17108 };\r
17109 },\r
17110 /**
17111 * Calls this function after the number of milliseconds specified, optionally in a specific scope. Example usage:
17112 *
17113 * var sayHi = function(name){
17114 * alert('Hi, ' + name);
17115 * }
17116 *
17117 * // executes immediately:
17118 * sayHi('Fred');
17119 *
17120 * // executes after 2 seconds:
17121 * Ext.Function.defer(sayHi, 2000, this, ['Fred']);
17122 *
17123 * // this syntax is sometimes useful for deferring
17124 * // execution of an anonymous function:
17125 * Ext.Function.defer(function(){
17126 * alert('Anonymous');
17127 * }, 100);
17128 *
17129 * {@link Ext#defer Ext.defer} is alias for {@link Ext.Function#defer Ext.Function.defer}
17130 *
17131 * @param {Function} fn The function to defer.
17132 * @param {Number} millis The number of milliseconds for the `setTimeout` call
17133 * (if less than or equal to 0 the function is executed immediately).
17134 * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
17135 * **If omitted, defaults to the browser window.**
17136 * @param {Array} [args] Overrides arguments for the call. Defaults to the arguments passed by the caller.
17137 * @param {Boolean/Number} [appendArgs=false] If `true` args are appended to call args instead of overriding,
17138 * or, if a number, then the args are inserted at the specified position.
17139 * @return {Number} The timeout id that can be used with `clearTimeout`.
17140 */\r
17141 defer: function(fn, millis, scope, args, appendArgs) {\r
17142 fn = Ext.Function.bind(fn, scope, args, appendArgs);\r
17143 if (millis > 0) {\r
17144 return setTimeout(function() {\r
17145 if (Ext.elevateFunction) {\r
17146 Ext.elevateFunction(fn);\r
17147 } else {\r
17148 fn();\r
17149 }\r
17150 }, millis);\r
17151 }\r
17152 fn();\r
17153 return 0;\r
17154 },\r
17155 /**
17156 * Calls this function repeatedly at a given interval, optionally in a specific scope.
17157 *
17158 * {@link Ext#defer Ext.defer} is alias for {@link Ext.Function#defer Ext.Function.defer}
17159 *
17160 * @param {Function} fn The function to defer.
17161 * @param {Number} millis The number of milliseconds for the `setInterval` call
17162 * @param {Object} scope (optional) The scope (`this` reference) in which the function is executed.
17163 * **If omitted, defaults to the browser window.**
17164 * @param {Array} [args] Overrides arguments for the call. Defaults to the arguments passed by the caller.
17165 * @param {Boolean/Number} [appendArgs=false] If `true` args are appended to call args instead of overriding,
17166 * or, if a number, then the args are inserted at the specified position.
17167 * @return {Number} The interval id that can be used with `clearInterval`.
17168 */\r
17169 interval: function(fn, millis, scope, args, appendArgs) {\r
17170 fn = Ext.Function.bind(fn, scope, args, appendArgs);\r
17171 return setInterval(function() {\r
17172 if (Ext.elevateFunction) {\r
17173 Ext.elevateFunction(fn);\r
17174 } else {\r
17175 fn();\r
17176 }\r
17177 }, millis);\r
17178 },\r
17179 /**
17180 * Create a combined function call sequence of the original function + the passed function.
17181 * The resulting function returns the results of the original function.
17182 * The passed function is called with the parameters of the original function. Example usage:
17183 *
17184 * var sayHi = function(name){
17185 * alert('Hi, ' + name);
17186 * };
17187 *
17188 * sayHi('Fred'); // alerts "Hi, Fred"
17189 *
17190 * var sayGoodbye = Ext.Function.createSequence(sayHi, function(name){
17191 * alert('Bye, ' + name);
17192 * });
17193 *
17194 * sayGoodbye('Fred'); // both alerts show
17195 *
17196 * @param {Function} originalFn The original function.
17197 * @param {Function} newFn The function to sequence.
17198 * @param {Object} [scope] The scope (`this` reference) in which the passed function is executed.
17199 * If omitted, defaults to the scope in which the original function is called or the
17200 * default global environment object (usually the browser window).
17201 * @return {Function} The new function.
17202 */\r
17203 createSequence: function(originalFn, newFn, scope) {\r
17204 if (!newFn) {\r
17205 return originalFn;\r
17206 } else {\r
17207 return function() {\r
17208 var result = originalFn.apply(this, arguments);\r
17209 newFn.apply(scope || this, arguments);\r
17210 return result;\r
17211 };\r
17212 }\r
17213 },\r
17214 /**
17215 * Creates a delegate function, optionally with a bound scope which, when called, buffers
17216 * the execution of the passed function for the configured number of milliseconds.
17217 * If called again within that period, the impending invocation will be canceled, and the
17218 * timeout period will begin again.
17219 *
17220 * @param {Function} fn The function to invoke on a buffered timer.
17221 * @param {Number} buffer The number of milliseconds by which to buffer the invocation of the
17222 * function.
17223 * @param {Object} [scope] The scope (`this` reference) in which.
17224 * the passed function is executed. If omitted, defaults to the scope specified by the caller.
17225 * @param {Array} [args] Override arguments for the call. Defaults to the arguments
17226 * passed by the caller.
17227 * @return {Function} A function which invokes the passed function after buffering for the specified time.
17228 */\r
17229 createBuffered: function(fn, buffer, scope, args) {\r
17230 var timerId;\r
17231 return function() {\r
17232 var callArgs = args || Array.prototype.slice.call(arguments, 0),\r
17233 me = scope || this;\r
17234 if (timerId) {\r
17235 clearTimeout(timerId);\r
17236 }\r
17237 timerId = setTimeout(function() {\r
17238 if (Ext.elevateFunction) {\r
17239 Ext.elevateFunction(fn, me, callArgs);\r
17240 } else {\r
17241 fn.apply(me, callArgs);\r
17242 }\r
17243 }, buffer);\r
17244 };\r
17245 },\r
17246 /**
17247 * Creates a wrapped function that, when invoked, defers execution until the next
17248 * animation frame
17249 * @private
17250 * @param {Function} fn The function to call.
17251 * @param {Object} [scope] The scope (`this` reference) in which the function is executed. Defaults to the window object.
17252 * @param {Array} [args] The argument list to pass to the function.
17253 * @param {Number} [queueStrategy=3] A bit flag that indicates how multiple calls to
17254 * the returned function within the same animation frame should be handled.
17255 *
17256 * - 1: All calls will be queued - FIFO order
17257 * - 2: Only the first call will be queued
17258 * - 3: The last call will replace all previous calls
17259 *
17260 * @return {Function}
17261 */\r
17262 createAnimationFrame: function(fn, scope, args, queueStrategy) {\r
17263 var timerId;\r
17264 queueStrategy = queueStrategy || 3;\r
17265 return function() {\r
17266 var callArgs = args || Array.prototype.slice.call(arguments, 0);\r
17267 scope = scope || this;\r
17268 if (queueStrategy === 3 && timerId) {\r
17269 ExtFunction.cancelAnimationFrame(timerId);\r
17270 }\r
17271 if ((queueStrategy & 1) || !timerId) {\r
17272 timerId = ExtFunction.requestAnimationFrame(function() {\r
17273 timerId = null;\r
17274 fn.apply(scope, callArgs);\r
17275 });\r
17276 }\r
17277 };\r
17278 },\r
17279 /**
17280 * @private
17281 * Schedules the passed function to be called on the next animation frame.
17282 * @param {Function} fn The function to call.
17283 * @param {Object} [scope] The scope (`this` reference) in which the function is executed. Defaults to the window object.
17284 * @param {Mixed[]} [args] The argument list to pass to the function.
17285 *
17286 * @return {Number} Timer id for the new animation frame to use when canceling it.
17287 */\r
17288 requestAnimationFrame: function(fn, scope, args) {\r
17289 var id = ++idSource,\r
17290 // Ids start at 1\r
17291 handler = Array.prototype.slice.call(arguments, 0);\r
17292 handler[3] = id;\r
17293 animFrameMap[id] = 1;\r
17294 // A flag to indicate that the timer exists\r
17295 // We might be in fireHandlers at this moment but this new entry will not\r
17296 // be executed until the next frame\r
17297 animFrameHandlers.push(handler);\r
17298 if (!animFrameId) {\r
17299 animFrameId = requestAnimFrame(Ext.elevateFunction ? fireElevatedHandlers : fireHandlers);\r
17300 }\r
17301 return id;\r
17302 },\r
17303 cancelAnimationFrame: function(id) {\r
17304 // Don't remove any handlers from animFrameHandlers array, because\r
17305 // the might be in use at the moment (when cancelAnimationFrame is called).\r
17306 // Just remove the handler id from the map so it will not be executed\r
17307 delete animFrameMap[id];\r
17308 },\r
17309 /**
17310 * Creates a throttled version of the passed function which, when called repeatedly and
17311 * rapidly, invokes the passed function only after a certain interval has elapsed since the
17312 * previous invocation.
17313 *
17314 * This is useful for wrapping functions which may be called repeatedly, such as
17315 * a handler of a mouse move event when the processing is expensive.
17316 *
17317 * @param {Function} fn The function to execute at a regular time interval.
17318 * @param {Number} interval The interval in milliseconds on which the passed function is executed.
17319 * @param {Object} [scope] The scope (`this` reference) in which
17320 * the passed function is executed. If omitted, defaults to the scope specified by the caller.
17321 * @return {Function} A function which invokes the passed function at the specified interval.
17322 */\r
17323 createThrottled: function(fn, interval, scope) {\r
17324 var lastCallTime = 0,\r
17325 elapsed, lastArgs, timer,\r
17326 execute = function() {\r
17327 if (Ext.elevateFunction) {\r
17328 Ext.elevateFunction(fn, scope, lastArgs);\r
17329 } else {\r
17330 fn.apply(scope, lastArgs);\r
17331 }\r
17332 lastCallTime = Ext.now();\r
17333 timer = null;\r
17334 };\r
17335 return function() {\r
17336 // Use scope of last call unless the creator specified a scope\r
17337 if (!scope) {\r
17338 scope = this;\r
17339 }\r
17340 elapsed = Ext.now() - lastCallTime;\r
17341 lastArgs = arguments;\r
17342 // If this is the first invocation, or the throttle interval has been reached, clear any\r
17343 // pending invocation, and call the target function now.\r
17344 if (elapsed >= interval) {\r
17345 clearTimeout(timer);\r
17346 execute();\r
17347 }\r
17348 // Throttle interval has not yet been reached. Only set the timer to fire if not already set.\r
17349 else if (!timer) {\r
17350 timer = Ext.defer(execute, interval - elapsed);\r
17351 }\r
17352 };\r
17353 },\r
17354 /**
17355 * Wraps the passed function in a barrier function which will call the passed function after the passed number of invocations.
17356 * @param {Number} count The number of invocations which will result in the calling of the passed function.
17357 * @param {Function} fn The function to call after the required number of invocations.
17358 * @param {Object} scope The scope (`this` reference) in which the function will be called.
17359 */\r
17360 createBarrier: function(count, fn, scope) {\r
17361 return function() {\r
17362 if (!--count) {\r
17363 fn.apply(scope, arguments);\r
17364 }\r
17365 };\r
17366 },\r
17367 /**
17368 * Adds behavior to an existing method that is executed before the
17369 * original behavior of the function. For example:
17370 *
17371 * var soup = {
17372 * contents: [],
17373 * add: function(ingredient) {
17374 * this.contents.push(ingredient);
17375 * }
17376 * };
17377 * Ext.Function.interceptBefore(soup, "add", function(ingredient){
17378 * if (!this.contents.length && ingredient !== "water") {
17379 * // Always add water to start with
17380 * this.contents.push("water");
17381 * }
17382 * });
17383 * soup.add("onions");
17384 * soup.add("salt");
17385 * soup.contents; // will contain: water, onions, salt
17386 *
17387 * @param {Object} object The target object
17388 * @param {String} methodName Name of the method to override
17389 * @param {Function} fn Function with the new behavior. It will
17390 * be called with the same arguments as the original method. The
17391 * return value of this function will be the return value of the
17392 * new method.
17393 * @param {Object} [scope] The scope to execute the interceptor function. Defaults to the object.
17394 * @return {Function} The new function just created.
17395 */\r
17396 interceptBefore: function(object, methodName, fn, scope) {\r
17397 var method = object[methodName] || Ext.emptyFn;\r
17398 return (object[methodName] = function() {\r
17399 var ret = fn.apply(scope || this, arguments);\r
17400 method.apply(this, arguments);\r
17401 return ret;\r
17402 });\r
17403 },\r
17404 /**
17405 * Adds behavior to an existing method that is executed after the
17406 * original behavior of the function. For example:
17407 *
17408 * var soup = {
17409 * contents: [],
17410 * add: function(ingredient) {
17411 * this.contents.push(ingredient);
17412 * }
17413 * };
17414 * Ext.Function.interceptAfter(soup, "add", function(ingredient){
17415 * // Always add a bit of extra salt
17416 * this.contents.push("salt");
17417 * });
17418 * soup.add("water");
17419 * soup.add("onions");
17420 * soup.contents; // will contain: water, salt, onions, salt
17421 *
17422 * @param {Object} object The target object
17423 * @param {String} methodName Name of the method to override
17424 * @param {Function} fn Function with the new behavior. It will
17425 * be called with the same arguments as the original method. The
17426 * return value of this function will be the return value of the
17427 * new method.
17428 * @param {Object} [scope] The scope to execute the interceptor function. Defaults to the object.
17429 * @return {Function} The new function just created.
17430 */\r
17431 interceptAfter: function(object, methodName, fn, scope) {\r
17432 var method = object[methodName] || Ext.emptyFn;\r
17433 return (object[methodName] = function() {\r
17434 method.apply(this, arguments);\r
17435 return fn.apply(scope || this, arguments);\r
17436 });\r
17437 },\r
17438 makeCallback: function(callback, scope) {\r
17439 if (!scope[callback]) {\r
17440 if (scope.$className) {\r
17441 Ext.raise('No method "' + callback + '" on ' + scope.$className);\r
17442 }\r
17443 Ext.raise('No method "' + callback + '"');\r
17444 }\r
17445 return function() {\r
17446 return scope[callback].apply(scope, arguments);\r
17447 };\r
17448 },\r
17449 /**
17450 * Returns a wrapper function that caches the return value for previously
17451 * processed function argument(s).
17452 *
17453 * For example:
17454 *
17455 * function factorial (value) {
17456 * var ret = value;
17457 *
17458 * while (--value > 1) {
17459 * ret *= value;
17460 * }
17461 *
17462 * return ret;
17463 * }
17464 *
17465 * Each call to `factorial` will loop and multiply to produce the answer. Using
17466 * this function we can wrap the above and cache its answers:
17467 *
17468 * factorial = Ext.Function.memoize(factorial);
17469 *
17470 * The returned function operates in the same manner as before, but results are
17471 * stored in a cache to avoid calling the wrapped function when given the same
17472 * arguments.
17473 *
17474 * var x = factorial(20); // first time; call real factorial()
17475 * var y = factorial(20); // second time; return value from first call
17476 *
17477 * To support multi-argument methods, you will need to provide a `hashFn`.
17478 *
17479 * function permutation (n, k) {
17480 * return factorial(n) / factorial(n - k);
17481 * }
17482 *
17483 * permutation = Ext.Function.memoize(permutation, null, function (n, k) {
17484 * n + '-' + k;
17485 * });
17486 *
17487 * In this case, the `memoize` of `factorial` is sufficient optimization, but the
17488 * example is simply to illustrate how to generate a unique key for an expensive,
17489 * multi-argument method.
17490 *
17491 * **IMPORTANT**: This cache is unbounded so be cautious of memory leaks if the
17492 * `memoize`d function is kept indefinitely or is given an unbounded set of
17493 * possible arguments.
17494 *
17495 * @param {Function} fn Function to wrap.
17496 * @param {Object} scope Optional scope in which to execute the wrapped function.
17497 * @param {Function} hashFn Optional function used to compute a hash key for
17498 * storing the result, based on the arguments to the original function.
17499 * @return {Function} The caching wrapper function.
17500 * @since 6.0.0
17501 */\r
17502 memoize: function(fn, scope, hashFn) {\r
17503 var memo = {},\r
17504 isFunc = hashFn && Ext.isFunction(hashFn);\r
17505 return function(value) {\r
17506 var key = isFunc ? hashFn.apply(scope, arguments) : value;\r
17507 if (!(key in memo)) {\r
17508 memo[key] = fn.apply(scope, arguments);\r
17509 }\r
17510 return memo[key];\r
17511 };\r
17512 }\r
17513 };\r
17514 // ExtFunction\r
17515 /**
17516 * @member Ext
17517 * @method asap
17518 * Schedules the specified callback function to be executed on the next turn of the
17519 * event loop. Where available, this method uses the browser's `setImmediate` API. If
17520 * not available, this method substitutes `setTimeout(0)`. Though not a perfect
17521 * replacement for `setImmediate` it is sufficient for many use cases.
17522 *
17523 * For more details see [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/setImmediate).
17524 *
17525 * @param {Function} fn Callback function.
17526 * @param {Object} [scope] The scope for the callback (`this` pointer).
17527 * @param {Mixed[]} [parameters] Additional parameters to pass to `fn`.
17528 * @return {Number} A cancelation id for `{@link Ext#asapCancel}`.
17529 */\r
17530 Ext.asap = hasImmediate ? function(fn, scope, parameters) {\r
17531 if (scope != null || parameters != null) {\r
17532 fn = ExtFunction.bind(fn, scope, parameters);\r
17533 }\r
17534 return setImmediate(function() {\r
17535 if (Ext.elevateFunction) {\r
17536 Ext.elevateFunction(fn);\r
17537 } else {\r
17538 fn();\r
17539 }\r
17540 });\r
17541 } : function(fn, scope, parameters) {\r
17542 if (scope != null || parameters != null) {\r
17543 fn = ExtFunction.bind(fn, scope, parameters);\r
17544 }\r
17545 return setTimeout(function() {\r
17546 if (Ext.elevateFunction) {\r
17547 Ext.elevateFunction(fn);\r
17548 } else {\r
17549 fn();\r
17550 }\r
17551 }, 0, true);\r
17552 } , /**
17553 * @member Ext
17554 * @method asapCancel
17555 * Cancels a previously scheduled call to `{@link Ext#asap}`.
17556 *
17557 * var asapId = Ext.asap(me.method, me);
17558 * ...
17559 *
17560 * if (nevermind) {
17561 * Ext.apasCancel(asapId);
17562 * }
17563 *
17564 * @param {Number} id The id returned by `{@link Ext#asap}`.
17565 */\r
17566 Ext.asapCancel = hasImmediate ? function(id) {\r
17567 clearImmediate(id);\r
17568 } : function(id) {\r
17569 clearTimeout(id);\r
17570 };\r
17571 /**
17572 * @method
17573 * @member Ext
17574 * @inheritdoc Ext.Function#defer
17575 */\r
17576 Ext.defer = ExtFunction.defer;\r
17577 /**
17578 * @method
17579 * @member Ext
17580 * @inheritdoc Ext.Function#interval
17581 */\r
17582 Ext.interval = ExtFunction.interval;\r
17583 /**
17584 * @method
17585 * @member Ext
17586 * @inheritdoc Ext.Function#pass
17587 */\r
17588 Ext.pass = ExtFunction.pass;\r
17589 /**
17590 * @method
17591 * @member Ext
17592 * @inheritdoc Ext.Function#bind
17593 */\r
17594 Ext.bind = ExtFunction.bind;\r
17595 Ext.deferCallback = ExtFunction.requestAnimationFrame;\r
17596 return ExtFunction;\r
17597})();\r
17598\r
17599/**
17600 * @class Ext.Number
17601 *
17602 * A collection of useful static methods to deal with numbers
17603 * @singleton
17604 */\r
17605Ext.Number = (new function() {\r
17606 // jshint ignore:line\r
17607 // @define Ext.lang.Number\r
17608 // @define Ext.Number\r
17609 // @require Ext\r
17610 var ExtNumber = this,\r
17611 isToFixedBroken = (0.9).toFixed() !== '1',\r
17612 math = Math,\r
17613 ClipDefault = {\r
17614 count: false,\r
17615 inclusive: false,\r
17616 wrap: true\r
17617 };\r
17618 Ext.apply(ExtNumber, {\r
17619 Clip: {\r
17620 DEFAULT: ClipDefault,\r
17621 COUNT: Ext.applyIf({\r
17622 count: true\r
17623 }, ClipDefault),\r
17624 INCLUSIVE: Ext.applyIf({\r
17625 inclusive: true\r
17626 }, ClipDefault),\r
17627 NOWRAP: Ext.applyIf({\r
17628 wrap: false\r
17629 }, ClipDefault)\r
17630 },\r
17631 /**
17632 * Coerces a given index into a valid index given a `length`.
17633 *
17634 * Negative indexes are interpreted starting at the end of the collection. That is,
17635 * a value of -1 indicates the last item, or equivalent to `length - 1`.
17636 *
17637 * When handling methods that take "begin" and "end" arguments like most array or
17638 * string methods, this method can be used like so:
17639 *
17640 * function foo (array, begin, end) {
17641 * var range = Ext.Number.clipIndices(array.length, [begin, end]);
17642 *
17643 * begin = range[0];
17644 * end = range[1];
17645 *
17646 * // 0 <= begin <= end <= array.length
17647 *
17648 * var length = end - begin;
17649 * }
17650 *
17651 * For example:
17652 *
17653 * +---+---+---+---+---+---+---+---+
17654 * | | | | | | | | | length = 8
17655 * +---+---+---+---+---+---+---+---+
17656 * 0 1 2 3 4 5 6 7
17657 * -8 -7 -6 -5 -4 -3 -2 -1
17658 *
17659 * console.log(Ext.Number.clipIndices(8, [3, 10]); // logs "[3, 8]"
17660 * console.log(Ext.Number.clipIndices(8, [-5]); // logs "[3, 8]"
17661 * console.log(Ext.Number.clipIndices(8, []);
17662 * console.log(Ext.Number.clipIndices(8, []);
17663 *
17664 * @param {Number} length
17665 * @param {Number[]} indices
17666 * @param {Object} [options] An object with different option flags.
17667 * @param {Boolean} [options.count=false] The second number in `indices` is the
17668 * count not and an index.
17669 * @param {Boolean} [options.inclusive=false] The second number in `indices` is
17670 * "inclusive" meaning that the item should be considered in the range. Normally,
17671 * the second number is considered the first item outside the range or as an
17672 * "exclusive" bound.
17673 * @param {Boolean} [options.wrap=true] Wraps negative numbers backwards from the
17674 * end of the array. Passing `false` simply clips negative index values at 0.
17675 * @return {Number[]} The normalized `[begin, end]` array where `end` is now
17676 * exclusive such that `length = end - begin`. Both values are between 0 and the
17677 * given `length` and `end` will not be less-than `begin`.
17678 */\r
17679 clipIndices: function(length, indices, options) {\r
17680 options = options || ClipDefault;\r
17681 var defaultValue = 0,\r
17682 // default value for "begin"\r
17683 wrap = options.wrap,\r
17684 begin, end, i;\r
17685 indices = indices || [];\r
17686 for (i = 0; i < 2; ++i) {\r
17687 // names are off on first pass but used this way so things make sense\r
17688 // following the loop..\r
17689 begin = end;\r
17690 // pick up and keep the result from the first loop\r
17691 end = indices[i];\r
17692 if (end == null) {\r
17693 end = defaultValue;\r
17694 } else if (i && options.count) {\r
17695 end += begin;\r
17696 // this is the length not "end" so convert to "end"\r
17697 end = (end > length) ? length : end;\r
17698 } else {\r
17699 if (wrap) {\r
17700 end = (end < 0) ? (length + end) : end;\r
17701 }\r
17702 if (i && options.inclusive) {\r
17703 ++end;\r
17704 }\r
17705 end = (end < 0) ? 0 : ((end > length) ? length : end);\r
17706 }\r
17707 defaultValue = length;\r
17708 }\r
17709 // default value for "end"\r
17710 // after loop:\r
17711 // 0 <= begin <= length (calculated from indices[0])\r
17712 // 0 <= end <= length (calculated from indices[1])\r
17713 indices[0] = begin;\r
17714 indices[1] = (end < begin) ? begin : end;\r
17715 return indices;\r
17716 },\r
17717 /**
17718 * Checks whether or not the passed number is within a desired range. If the number is already within the
17719 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
17720 * exceeded. Note that this method returns the constrained value but does not change the current number.
17721 * @param {Number} number The number to check
17722 * @param {Number} min The minimum number in the range
17723 * @param {Number} max The maximum number in the range
17724 * @return {Number} The constrained value if outside the range, otherwise the current value
17725 */\r
17726 constrain: function(number, min, max) {\r
17727 var x = parseFloat(number);\r
17728 // (x < Nan) || (x < undefined) == false\r
17729 // same for (x > NaN) || (x > undefined)\r
17730 // sadly this is not true of null - (1 > null)\r
17731 if (min === null) {\r
17732 min = number;\r
17733 }\r
17734 if (max === null) {\r
17735 max = number;\r
17736 }\r
17737 // Watch out for NaN in Chrome 18\r
17738 // V8bug: http://code.google.com/p/v8/issues/detail?id=2056\r
17739 // Operators are faster than Math.min/max. See http://jsperf.com/number-constrain\r
17740 return (x < min) ? min : ((x > max) ? max : x);\r
17741 },\r
17742 /**
17743 * Snaps the passed number between stopping points based upon a passed increment value.
17744 *
17745 * The difference between this and {@link #snapInRange} is that {@link #snapInRange} uses the minValue
17746 * when calculating snap points:
17747 *
17748 * r = Ext.Number.snap(56, 2, 55, 65); // Returns 56 - snap points are zero based
17749 *
17750 * r = Ext.Number.snapInRange(56, 2, 55, 65); // Returns 57 - snap points are based from minValue
17751 *
17752 * @param {Number} value The unsnapped value.
17753 * @param {Number} increment The increment by which the value must move.
17754 * @param {Number} minValue The minimum value to which the returned value must be constrained. Overrides the increment.
17755 * @param {Number} maxValue The maximum value to which the returned value must be constrained. Overrides the increment.
17756 * @return {Number} The value of the nearest snap target.
17757 */\r
17758 snap: function(value, increment, minValue, maxValue) {\r
17759 var m;\r
17760 // If no value passed, or minValue was passed and value is less than minValue (anything < undefined is false)\r
17761 // Then use the minValue (or zero if the value was undefined)\r
17762 if (value === undefined || value < minValue) {\r
17763 return minValue || 0;\r
17764 }\r
17765 if (increment) {\r
17766 m = value % increment;\r
17767 if (m !== 0) {\r
17768 value -= m;\r
17769 if (m * 2 >= increment) {\r
17770 value += increment;\r
17771 } else if (m * 2 < -increment) {\r
17772 value -= increment;\r
17773 }\r
17774 }\r
17775 }\r
17776 return ExtNumber.constrain(value, minValue, maxValue);\r
17777 },\r
17778 /**
17779 * Snaps the passed number between stopping points based upon a passed increment value.
17780 *
17781 * The difference between this and {@link #snap} is that {@link #snap} does not use the minValue
17782 * when calculating snap points:
17783 *
17784 * r = Ext.Number.snap(56, 2, 55, 65); // Returns 56 - snap points are zero based
17785 *
17786 * r = Ext.Number.snapInRange(56, 2, 55, 65); // Returns 57 - snap points are based from minValue
17787 *
17788 * @param {Number} value The unsnapped value.
17789 * @param {Number} increment The increment by which the value must move.
17790 * @param {Number} [minValue=0] The minimum value to which the returned value must be constrained.
17791 * @param {Number} [maxValue=Infinity] The maximum value to which the returned value must be constrained.
17792 * @return {Number} The value of the nearest snap target.
17793 */\r
17794 snapInRange: function(value, increment, minValue, maxValue) {\r
17795 var tween;\r
17796 // default minValue to zero\r
17797 minValue = (minValue || 0);\r
17798 // If value is undefined, or less than minValue, use minValue\r
17799 if (value === undefined || value < minValue) {\r
17800 return minValue;\r
17801 }\r
17802 // Calculate how many snap points from the minValue the passed value is.\r
17803 if (increment && (tween = ((value - minValue) % increment))) {\r
17804 value -= tween;\r
17805 tween *= 2;\r
17806 if (tween >= increment) {\r
17807 value += increment;\r
17808 }\r
17809 }\r
17810 // If constraining within a maximum, ensure the maximum is on a snap point\r
17811 if (maxValue !== undefined) {\r
17812 if (value > (maxValue = ExtNumber.snapInRange(maxValue, increment, minValue))) {\r
17813 value = maxValue;\r
17814 }\r
17815 }\r
17816 return value;\r
17817 },\r
17818 /**
17819 * Returns the sign of the given number. See also MDN for Math.sign documentation
17820 * for the standard method this method emulates.
17821 * @param {Number} x The number.
17822 * @return {Number} The sign of the number `x`, indicating whether the number is
17823 * positive (1), negative (-1) or zero (0).
17824 */\r
17825 sign: function(x) {\r
17826 x = +x;\r
17827 // force to a Number\r
17828 if (x === 0 || isNaN(x)) {\r
17829 return x;\r
17830 }\r
17831 return (x > 0) ? 1 : -1;\r
17832 },\r
17833 /**
17834 * @method
17835 * Formats a number using fixed-point notation
17836 * @param {Number} value The number to format
17837 * @param {Number} precision The number of digits to show after the decimal point
17838 */\r
17839 toFixed: isToFixedBroken ? function(value, precision) {\r
17840 precision = precision || 0;\r
17841 var pow = math.pow(10, precision);\r
17842 return (math.round(value * pow) / pow).toFixed(precision);\r
17843 } : function(value, precision) {\r
17844 return value.toFixed(precision);\r
17845 },\r
17846 /**
17847 * Validate that a value is numeric and convert it to a number if necessary. Returns the specified default value if
17848 * it is not.
17849
17850 Ext.Number.from('1.23', 1); // returns 1.23
17851 Ext.Number.from('abc', 1); // returns 1
17852
17853 * @param {Object} value
17854 * @param {Number} defaultValue The value to return if the original value is non-numeric
17855 * @return {Number} value, if numeric, defaultValue otherwise
17856 */\r
17857 from: function(value, defaultValue) {\r
17858 if (isFinite(value)) {\r
17859 value = parseFloat(value);\r
17860 }\r
17861 return !isNaN(value) ? value : defaultValue;\r
17862 },\r
17863 /**
17864 * Returns a random integer between the specified range (inclusive)
17865 * @param {Number} from Lowest value to return.
17866 * @param {Number} to Highest value to return.
17867 * @return {Number} A random integer within the specified range.
17868 */\r
17869 randomInt: function(from, to) {\r
17870 return math.floor(math.random() * (to - from + 1) + from);\r
17871 },\r
17872 /**
17873 * Corrects floating point numbers that overflow to a non-precise
17874 * value because of their floating nature, for example `0.1 + 0.2`
17875 * @param {Number} n The number
17876 * @return {Number} The correctly rounded number
17877 */\r
17878 correctFloat: function(n) {\r
17879 // This is to correct the type of errors where 2 floats end with\r
17880 // a long string of decimals, eg 0.1 + 0.2. When they overflow in this\r
17881 // manner, they usually go to 15-16 decimals, so we cut it off at 14.\r
17882 return parseFloat(n.toPrecision(14));\r
17883 }\r
17884 });\r
17885 /**
17886 * @deprecated 4.0.0 Please use {@link Ext.Number#from} instead.
17887 * @member Ext
17888 * @method num
17889 * @inheritdoc Ext.Number#from
17890 */\r
17891 Ext.num = function() {\r
17892 return ExtNumber.from.apply(this, arguments);\r
17893 };\r
17894}());\r
17895\r
17896/**
17897 * @class Ext.Object
17898 *
17899 * A collection of useful static methods to deal with objects.
17900 *
17901 * @singleton
17902 */\r
17903(function() {\r
17904 // The "constructor" for chain:\r
17905 var TemplateClass = function() {},\r
17906 queryRe = /^\?/,\r
17907 keyRe = /(\[):?([^\]]*)\]/g,\r
17908 nameRe = /^([^\[]+)/,\r
17909 plusRe = /\+/g,\r
17910 ExtObject = Ext.Object = {\r
17911 // @define Ext.lang.Object\r
17912 // @define Ext.Object\r
17913 // @require Ext\r
17914 // @require Ext.lang.Date\r
17915 /**
17916 * @method
17917 * Returns a new object with the given object as the prototype chain. This method is
17918 * designed to mimic the ECMA standard `Object.create` method and is assigned to that
17919 * function when it is available.
17920 *
17921 * **NOTE** This method does not support the property definitions capability of the
17922 * `Object.create` method. Only the first argument is supported.
17923 *
17924 * @param {Object} object The prototype chain for the new object.
17925 */\r
17926 chain: Object.create || function(object) {\r
17927 TemplateClass.prototype = object;\r
17928 var result = new TemplateClass();\r
17929 TemplateClass.prototype = null;\r
17930 return result;\r
17931 },\r
17932 /**
17933 * This method removes all keys from the given object.
17934 * @param {Object} object The object from which to remove all keys.
17935 * @return {Object} The given object.
17936 */\r
17937 clear: function(object) {\r
17938 // Safe to delete during iteration\r
17939 for (var key in object) {\r
17940 delete object[key];\r
17941 }\r
17942 return object;\r
17943 },\r
17944 /**
17945 * Freezes the given object making it immutable. This operation is by default shallow
17946 * and does not effect objects referenced by the given object.
17947 *
17948 * @method
17949 * @param {Object} obj The object to freeze.
17950 * @param {Boolean} [deep=false] Pass `true` to freeze sub-objects recursively.
17951 * @return {Object} The given object `obj`.
17952 */\r
17953 freeze: Object.freeze ? function(obj, deep) {\r
17954 if (obj && typeof obj === 'object' && !Object.isFrozen(obj)) {\r
17955 Object.freeze(obj);\r
17956 if (deep) {\r
17957 for (var name in obj) {\r
17958 ExtObject.freeze(obj[name], deep);\r
17959 }\r
17960 }\r
17961 }\r
17962 return obj;\r
17963 } : Ext.identityFn,\r
17964 /**
17965 * Converts a `name` - `value` pair to an array of objects with support for nested structures. Useful to construct
17966 * query strings. For example:
17967 *
17968 * var objects = Ext.Object.toQueryObjects('hobbies', ['reading', 'cooking', 'swimming']);
17969 *
17970 * // objects then equals:
17971 * [
17972 * { name: 'hobbies', value: 'reading' },
17973 * { name: 'hobbies', value: 'cooking' },
17974 * { name: 'hobbies', value: 'swimming' },
17975 * ];
17976 *
17977 * var objects = Ext.Object.toQueryObjects('dateOfBirth', {
17978 * day: 3,
17979 * month: 8,
17980 * year: 1987,
17981 * extra: {
17982 * hour: 4
17983 * minute: 30
17984 * }
17985 * }, true); // Recursive
17986 *
17987 * // objects then equals:
17988 * [
17989 * { name: 'dateOfBirth[day]', value: 3 },
17990 * { name: 'dateOfBirth[month]', value: 8 },
17991 * { name: 'dateOfBirth[year]', value: 1987 },
17992 * { name: 'dateOfBirth[extra][hour]', value: 4 },
17993 * { name: 'dateOfBirth[extra][minute]', value: 30 },
17994 * ];
17995 *
17996 * @param {String} name
17997 * @param {Object/Array} value
17998 * @param {Boolean} [recursive=false] True to traverse object recursively
17999 * @return {Object[]}
18000 */\r
18001 toQueryObjects: function(name, value, recursive) {\r
18002 var self = ExtObject.toQueryObjects,\r
18003 objects = [],\r
18004 i, ln;\r
18005 if (Ext.isArray(value)) {\r
18006 for (i = 0 , ln = value.length; i < ln; i++) {\r
18007 if (recursive) {\r
18008 objects = objects.concat(self(name + '[' + i + ']', value[i], true));\r
18009 } else {\r
18010 objects.push({\r
18011 name: name,\r
18012 value: value[i]\r
18013 });\r
18014 }\r
18015 }\r
18016 } else if (Ext.isObject(value)) {\r
18017 for (i in value) {\r
18018 if (value.hasOwnProperty(i)) {\r
18019 if (recursive) {\r
18020 objects = objects.concat(self(name + '[' + i + ']', value[i], true));\r
18021 } else {\r
18022 objects.push({\r
18023 name: name,\r
18024 value: value[i]\r
18025 });\r
18026 }\r
18027 }\r
18028 }\r
18029 } else {\r
18030 objects.push({\r
18031 name: name,\r
18032 value: value\r
18033 });\r
18034 }\r
18035 return objects;\r
18036 },\r
18037 /**
18038 * Takes an object and converts it to an encoded query string.
18039 *
18040 * Non-recursive:
18041 *
18042 * Ext.Object.toQueryString({foo: 1, bar: 2}); // returns "foo=1&bar=2"
18043 * Ext.Object.toQueryString({foo: null, bar: 2}); // returns "foo=&bar=2"
18044 * Ext.Object.toQueryString({'some price': '$300'}); // returns "some%20price=%24300"
18045 * Ext.Object.toQueryString({date: new Date(2011, 0, 1)}); // returns "date=%222011-01-01T00%3A00%3A00%22"
18046 * Ext.Object.toQueryString({colors: ['red', 'green', 'blue']}); // returns "colors=red&colors=green&colors=blue"
18047 *
18048 * Recursive:
18049 *
18050 * Ext.Object.toQueryString({
18051 * username: 'Jacky',
18052 * dateOfBirth: {
18053 * day: 1,
18054 * month: 2,
18055 * year: 1911
18056 * },
18057 * hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
18058 * }, true); // returns the following string (broken down and url-decoded for ease of reading purpose):
18059 * // username=Jacky
18060 * // &dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911
18061 * // &hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&hobbies[3][0]=nested&hobbies[3][1]=stuff
18062 *
18063 * @param {Object} object The object to encode
18064 * @param {Boolean} [recursive=false] Whether or not to interpret the object in recursive format.
18065 * (PHP / Ruby on Rails servers and similar).
18066 * @return {String} queryString
18067 */\r
18068 toQueryString: function(object, recursive) {\r
18069 var paramObjects = [],\r
18070 params = [],\r
18071 i, j, ln, paramObject, value;\r
18072 for (i in object) {\r
18073 if (object.hasOwnProperty(i)) {\r
18074 paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));\r
18075 }\r
18076 }\r
18077 for (j = 0 , ln = paramObjects.length; j < ln; j++) {\r
18078 paramObject = paramObjects[j];\r
18079 value = paramObject.value;\r
18080 if (Ext.isEmpty(value)) {\r
18081 value = '';\r
18082 } else if (Ext.isDate(value)) {\r
18083 value = Ext.Date.toString(value);\r
18084 }\r
18085 params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));\r
18086 }\r
18087 return params.join('&');\r
18088 },\r
18089 /**
18090 * Converts a query string back into an object.
18091 *
18092 * Non-recursive:
18093 *
18094 * Ext.Object.fromQueryString("foo=1&bar=2"); // returns {foo: '1', bar: '2'}
18095 * Ext.Object.fromQueryString("foo=&bar=2"); // returns {foo: '', bar: '2'}
18096 * Ext.Object.fromQueryString("some%20price=%24300"); // returns {'some price': '$300'}
18097 * Ext.Object.fromQueryString("colors=red&colors=green&colors=blue"); // returns {colors: ['red', 'green', 'blue']}
18098 *
18099 * Recursive:
18100 *
18101 * Ext.Object.fromQueryString(
18102 * "username=Jacky&"+
18103 * "dateOfBirth[day]=1&dateOfBirth[month]=2&dateOfBirth[year]=1911&"+
18104 * "hobbies[0]=coding&hobbies[1]=eating&hobbies[2]=sleeping&"+
18105 * "hobbies[3][0]=nested&hobbies[3][1]=stuff", true);
18106 *
18107 * // returns
18108 * {
18109 * username: 'Jacky',
18110 * dateOfBirth: {
18111 * day: '1',
18112 * month: '2',
18113 * year: '1911'
18114 * },
18115 * hobbies: ['coding', 'eating', 'sleeping', ['nested', 'stuff']]
18116 * }
18117 *
18118 * @param {String} queryString The query string to decode
18119 * @param {Boolean} [recursive=false] Whether or not to recursively decode the string. This format is supported by
18120 * PHP / Ruby on Rails servers and similar.
18121 * @return {Object}
18122 */\r
18123 fromQueryString: function(queryString, recursive) {\r
18124 var parts = queryString.replace(queryRe, '').split('&'),\r
18125 object = {},\r
18126 temp, components, name, value, i, ln, part, j, subLn, matchedKeys, matchedName, keys, key, nextKey;\r
18127 for (i = 0 , ln = parts.length; i < ln; i++) {\r
18128 part = parts[i];\r
18129 if (part.length > 0) {\r
18130 components = part.split('=');\r
18131 name = components[0];\r
18132 name = name.replace(plusRe, '%20');\r
18133 name = decodeURIComponent(name);\r
18134 value = components[1];\r
18135 if (value !== undefined) {\r
18136 value = value.replace(plusRe, '%20');\r
18137 value = decodeURIComponent(value);\r
18138 } else {\r
18139 value = '';\r
18140 }\r
18141 if (!recursive) {\r
18142 if (object.hasOwnProperty(name)) {\r
18143 if (!Ext.isArray(object[name])) {\r
18144 object[name] = [\r
18145 object[name]\r
18146 ];\r
18147 }\r
18148 object[name].push(value);\r
18149 } else {\r
18150 object[name] = value;\r
18151 }\r
18152 } else {\r
18153 matchedKeys = name.match(keyRe);\r
18154 matchedName = name.match(nameRe);\r
18155 if (!matchedName) {\r
18156 throw new Error('[Ext.Object.fromQueryString] Malformed query string given, failed parsing name from "' + part + '"');\r
18157 }\r
18158 name = matchedName[0];\r
18159 keys = [];\r
18160 if (matchedKeys === null) {\r
18161 object[name] = value;\r
18162 \r
18163 continue;\r
18164 }\r
18165 for (j = 0 , subLn = matchedKeys.length; j < subLn; j++) {\r
18166 key = matchedKeys[j];\r
18167 key = (key.length === 2) ? '' : key.substring(1, key.length - 1);\r
18168 keys.push(key);\r
18169 }\r
18170 keys.unshift(name);\r
18171 temp = object;\r
18172 for (j = 0 , subLn = keys.length; j < subLn; j++) {\r
18173 key = keys[j];\r
18174 if (j === subLn - 1) {\r
18175 if (Ext.isArray(temp) && key === '') {\r
18176 temp.push(value);\r
18177 } else {\r
18178 temp[key] = value;\r
18179 }\r
18180 } else {\r
18181 if (temp[key] === undefined || typeof temp[key] === 'string') {\r
18182 nextKey = keys[j + 1];\r
18183 temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};\r
18184 }\r
18185 temp = temp[key];\r
18186 }\r
18187 }\r
18188 }\r
18189 }\r
18190 }\r
18191 return object;\r
18192 },\r
18193 /**
18194 * Iterates through an object and invokes the given callback function for each iteration.
18195 * The iteration can be stopped by returning `false` in the callback function. For example:
18196 *
18197 * var person = {
18198 * name: 'Jacky'
18199 * hairColor: 'black'
18200 * loves: ['food', 'sleeping', 'wife']
18201 * };
18202 *
18203 * Ext.Object.each(person, function(key, value, myself) {
18204 * console.log(key + ":" + value);
18205 *
18206 * if (key === 'hairColor') {
18207 * return false; // stop the iteration
18208 * }
18209 * });
18210 *
18211 * @param {Object} object The object to iterate
18212 * @param {Function} fn The callback function.
18213 * @param {String} fn.key
18214 * @param {Object} fn.value
18215 * @param {Object} fn.object The object itself
18216 * @param {Object} [scope] The execution scope (`this`) of the callback function
18217 */\r
18218 each: function(object, fn, scope) {\r
18219 var enumerables = Ext.enumerables,\r
18220 i, property;\r
18221 if (object) {\r
18222 scope = scope || object;\r
18223 for (property in object) {\r
18224 if (object.hasOwnProperty(property)) {\r
18225 if (fn.call(scope, property, object[property], object) === false) {\r
18226 return;\r
18227 }\r
18228 }\r
18229 }\r
18230 if (enumerables) {\r
18231 for (i = enumerables.length; i--; ) {\r
18232 if (object.hasOwnProperty(property = enumerables[i])) {\r
18233 if (fn.call(scope, property, object[property], object) === false) {\r
18234 return;\r
18235 }\r
18236 }\r
18237 }\r
18238 }\r
18239 }\r
18240 },\r
18241 /**
18242 * Iterates through an object and invokes the given callback function for each iteration.
18243 * The iteration can be stopped by returning `false` in the callback function. For example:
18244 *
18245 * var items = {
18246 * 1: 'Hello',
18247 * 2: 'World'
18248 * };
18249 *
18250 * Ext.Object.eachValue(items, function (value) {
18251 * console.log("Value: " + value);
18252 * });
18253 *
18254 * This will log 'Hello' and 'World' in no particular order. This method is useful
18255 * in cases where the keys are not important to the processing, just the values.
18256 *
18257 * @param {Object} object The object to iterate
18258 * @param {Function} fn The callback function.
18259 * @param {Object} fn.value The value of
18260 * @param {Object} [scope] The execution scope (`this`) of the callback function
18261 */\r
18262 eachValue: function(object, fn, scope) {\r
18263 var enumerables = Ext.enumerables,\r
18264 i, property;\r
18265 scope = scope || object;\r
18266 for (property in object) {\r
18267 if (object.hasOwnProperty(property)) {\r
18268 if (fn.call(scope, object[property]) === false) {\r
18269 return;\r
18270 }\r
18271 }\r
18272 }\r
18273 if (enumerables) {\r
18274 for (i = enumerables.length; i--; ) {\r
18275 if (object.hasOwnProperty(property = enumerables[i])) {\r
18276 if (fn.call(scope, object[property]) === false) {\r
18277 return;\r
18278 }\r
18279 }\r
18280 }\r
18281 }\r
18282 },\r
18283 /**
18284 * Merges any number of objects recursively without referencing them or their children.
18285 *
18286 * var extjs = {
18287 * companyName: 'Ext JS',
18288 * products: ['Ext JS', 'Ext GWT', 'Ext Designer'],
18289 * isSuperCool: true,
18290 * office: {
18291 * size: 2000,
18292 * location: 'Palo Alto',
18293 * isFun: true
18294 * }
18295 * };
18296 *
18297 * var newStuff = {
18298 * companyName: 'Sencha Inc.',
18299 * products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
18300 * office: {
18301 * size: 40000,
18302 * location: 'Redwood City'
18303 * }
18304 * };
18305 *
18306 * var sencha = Ext.Object.merge(extjs, newStuff);
18307 *
18308 * // extjs and sencha then equals to
18309 * {
18310 * companyName: 'Sencha Inc.',
18311 * products: ['Ext JS', 'Ext GWT', 'Ext Designer', 'Sencha Touch', 'Sencha Animator'],
18312 * isSuperCool: true,
18313 * office: {
18314 * size: 40000,
18315 * location: 'Redwood City',
18316 * isFun: true
18317 * }
18318 * }
18319 *
18320 * @param {Object} destination The object into which all subsequent objects are merged.
18321 * @param {Object...} object Any number of objects to merge into the destination.
18322 * @return {Object} merged The destination object with all passed objects merged in.
18323 */\r
18324 merge: function(destination) {\r
18325 var i = 1,\r
18326 ln = arguments.length,\r
18327 mergeFn = ExtObject.merge,\r
18328 cloneFn = Ext.clone,\r
18329 object, key, value, sourceKey;\r
18330 for (; i < ln; i++) {\r
18331 object = arguments[i];\r
18332 for (key in object) {\r
18333 value = object[key];\r
18334 if (value && value.constructor === Object) {\r
18335 sourceKey = destination[key];\r
18336 if (sourceKey && sourceKey.constructor === Object) {\r
18337 mergeFn(sourceKey, value);\r
18338 } else {\r
18339 destination[key] = cloneFn(value);\r
18340 }\r
18341 } else {\r
18342 destination[key] = value;\r
18343 }\r
18344 }\r
18345 }\r
18346 return destination;\r
18347 },\r
18348 /**
18349 * @private
18350 * @param destination
18351 */\r
18352 mergeIf: function(destination) {\r
18353 var i = 1,\r
18354 ln = arguments.length,\r
18355 cloneFn = Ext.clone,\r
18356 object, key, value;\r
18357 for (; i < ln; i++) {\r
18358 object = arguments[i];\r
18359 for (key in object) {\r
18360 if (!(key in destination)) {\r
18361 value = object[key];\r
18362 if (value && value.constructor === Object) {\r
18363 destination[key] = cloneFn(value);\r
18364 } else {\r
18365 destination[key] = value;\r
18366 }\r
18367 }\r
18368 }\r
18369 }\r
18370 return destination;\r
18371 },\r
18372 /**
18373 * Returns all keys of the given object as an array.
18374 *
18375 * @param {Object} object
18376 * @return {String[]} An array of keys from the object or any of its prototypes.
18377 * @method
18378 */\r
18379 getAllKeys: function(object) {\r
18380 var keys = [],\r
18381 property;\r
18382 for (property in object) {\r
18383 keys.push(property);\r
18384 }\r
18385 return keys;\r
18386 },\r
18387 /**
18388 * Returns the first matching key corresponding to the given value.
18389 * If no matching value is found, null is returned.
18390 *
18391 * var person = {
18392 * name: 'Jacky',
18393 * loves: 'food'
18394 * };
18395 *
18396 * alert(Ext.Object.getKey(person, 'food')); // alerts 'loves'
18397 *
18398 * @param {Object} object
18399 * @param {Object} value The value to find
18400 */\r
18401 getKey: function(object, value) {\r
18402 for (var property in object) {\r
18403 if (object.hasOwnProperty(property) && object[property] === value) {\r
18404 return property;\r
18405 }\r
18406 }\r
18407 return null;\r
18408 },\r
18409 /**
18410 * Gets all values of the given object as an array.
18411 *
18412 * var values = Ext.Object.getValues({
18413 * name: 'Jacky',
18414 * loves: 'food'
18415 * }); // ['Jacky', 'food']
18416 *
18417 * @param {Object} object
18418 * @return {Array} An array of values from the object
18419 */\r
18420 getValues: function(object) {\r
18421 var values = [],\r
18422 property;\r
18423 for (property in object) {\r
18424 if (object.hasOwnProperty(property)) {\r
18425 values.push(object[property]);\r
18426 }\r
18427 }\r
18428 return values;\r
18429 },\r
18430 /**
18431 * Returns the `hasOwnProperty` keys of the given object as an array.
18432 *
18433 * var values = Ext.Object.getKeys({
18434 * name: 'Jacky',
18435 * loves: 'food'
18436 * }); // ['name', 'loves']
18437 *
18438 * @param {Object} object
18439 * @return {String[]} An array of keys from the object
18440 * @method
18441 */\r
18442 getKeys: (typeof Object.keys == 'function') ? function(object) {\r
18443 if (!object) {\r
18444 return [];\r
18445 }\r
18446 return Object.keys(object);\r
18447 } : function(object) {\r
18448 var keys = [],\r
18449 property;\r
18450 for (property in object) {\r
18451 if (object.hasOwnProperty(property)) {\r
18452 keys.push(property);\r
18453 }\r
18454 }\r
18455 return keys;\r
18456 },\r
18457 /**
18458 * Gets the total number of this object's own properties
18459 *
18460 * var size = Ext.Object.getSize({
18461 * name: 'Jacky',
18462 * loves: 'food'
18463 * }); // size equals 2
18464 *
18465 * @param {Object} object
18466 * @return {Number} size
18467 */\r
18468 getSize: function(object) {\r
18469 var size = 0,\r
18470 property;\r
18471 for (property in object) {\r
18472 if (object.hasOwnProperty(property)) {\r
18473 size++;\r
18474 }\r
18475 }\r
18476 return size;\r
18477 },\r
18478 /**
18479 * Checks if there are any properties on this object.
18480 * @param {Object} object
18481 * @return {Boolean} `true` if there no properties on the object.
18482 */\r
18483 isEmpty: function(object) {\r
18484 for (var key in object) {\r
18485 if (object.hasOwnProperty(key)) {\r
18486 return false;\r
18487 }\r
18488 }\r
18489 return true;\r
18490 },\r
18491 /**
18492 * @method
18493 * Shallow compares the contents of 2 objects using strict equality. Objects are
18494 * considered equal if they both have the same set of properties and the
18495 * value for those properties equals the other in the corresponding object.
18496 *
18497 * // Returns true
18498 * Ext.Object.equals({
18499 * foo: 1,
18500 * bar: 2
18501 * }, {
18502 * foo: 1,
18503 * bar: 2
18504 * });
18505 *
18506 * @param {Object} object1
18507 * @param {Object} object2
18508 * @return {Boolean} `true` if the objects are equal.
18509 */\r
18510 equals: (function() {\r
18511 var check = function(o1, o2) {\r
18512 var key;\r
18513 for (key in o1) {\r
18514 if (o1.hasOwnProperty(key)) {\r
18515 if (o1[key] !== o2[key]) {\r
18516 return false;\r
18517 }\r
18518 }\r
18519 }\r
18520 return true;\r
18521 };\r
18522 return function(object1, object2) {\r
18523 // Short circuit if the same object is passed twice\r
18524 if (object1 === object2) {\r
18525 return true;\r
18526 }\r
18527 if (object1 && object2) {\r
18528 // Do the second check because we could have extra keys in\r
18529 // object2 that don't exist in object1.\r
18530 return check(object1, object2) && check(object2, object1);\r
18531 } else if (!object1 && !object2) {\r
18532 return object1 === object2;\r
18533 } else {\r
18534 return false;\r
18535 }\r
18536 };\r
18537 })(),\r
18538 /**
18539 * @private
18540 */\r
18541 fork: function(obj) {\r
18542 var ret, key, value;\r
18543 if (obj && obj.constructor === Object) {\r
18544 ret = ExtObject.chain(obj);\r
18545 for (key in obj) {\r
18546 value = obj[key];\r
18547 if (value) {\r
18548 if (value.constructor === Object) {\r
18549 ret[key] = ExtObject.fork(value);\r
18550 } else if (value instanceof Array) {\r
18551 ret[key] = Ext.Array.clone(value);\r
18552 }\r
18553 }\r
18554 }\r
18555 } else {\r
18556 ret = obj;\r
18557 }\r
18558 return ret;\r
18559 },\r
18560 defineProperty: ('defineProperty' in Object) ? Object.defineProperty : function(object, name, descriptor) {\r
18561 if (!Object.prototype.__defineGetter__) {\r
18562 return;\r
18563 }\r
18564 if (descriptor.get) {\r
18565 object.__defineGetter__(name, descriptor.get);\r
18566 }\r
18567 if (descriptor.set) {\r
18568 object.__defineSetter__(name, descriptor.set);\r
18569 }\r
18570 },\r
18571 /**
18572 * @private
18573 */\r
18574 classify: function(object) {\r
18575 var prototype = object,\r
18576 objectProperties = [],\r
18577 propertyClassesMap = {},\r
18578 objectClass = function() {\r
18579 var i = 0,\r
18580 ln = objectProperties.length,\r
18581 property;\r
18582 for (; i < ln; i++) {\r
18583 property = objectProperties[i];\r
18584 this[property] = new propertyClassesMap[property]();\r
18585 }\r
18586 },\r
18587 key, value;\r
18588 for (key in object) {\r
18589 if (object.hasOwnProperty(key)) {\r
18590 value = object[key];\r
18591 if (value && value.constructor === Object) {\r
18592 objectProperties.push(key);\r
18593 propertyClassesMap[key] = ExtObject.classify(value);\r
18594 }\r
18595 }\r
18596 }\r
18597 objectClass.prototype = prototype;\r
18598 return objectClass;\r
18599 }\r
18600 };\r
18601 /**
18602 * A convenient alias method for {@link Ext.Object#merge}.
18603 *
18604 * @member Ext
18605 * @method merge
18606 * @inheritdoc Ext.Object#merge
18607 */\r
18608 Ext.merge = Ext.Object.merge;\r
18609 /**
18610 * @private
18611 * @member Ext
18612 */\r
18613 Ext.mergeIf = Ext.Object.mergeIf;\r
18614}());\r
18615\r
18616/*
18617 * This file contains miscellaneous utility methods that depends on various helper classes
18618 * like `Ext.Array` and `Ext.Date`. Historically these methods were defined in Ext.js or
18619 * Ext-more.js but that creates circular dependencies so they were consolidated here.
18620 */\r
18621Ext.apply(Ext, {\r
18622 // @define Ext.Util\r
18623 // @require Ext\r
18624 // @require Ext.lang.*\r
18625 // shortcut for the special named scopes for listener scope resolution\r
18626 _namedScopes: {\r
18627 'this': {\r
18628 isThis: 1\r
18629 },\r
18630 controller: {\r
18631 isController: 1\r
18632 },\r
18633 // these two are private, used to indicate that listeners were declared on the\r
18634 // class body with either an unspecified scope, or scope:'controller'\r
18635 self: {\r
18636 isSelf: 1\r
18637 },\r
18638 'self.controller': {\r
18639 isSelf: 1,\r
18640 isController: 1\r
18641 }\r
18642 },\r
18643 escapeId: (function() {\r
18644 var validIdRe = /^[a-zA-Z_][a-zA-Z0-9_\-]*$/i,\r
18645 escapeRx = /([\W]{1})/g,\r
18646 leadingNumRx = /^(\d)/g,\r
18647 escapeFn = function(match, capture) {\r
18648 return "\\" + capture;\r
18649 },\r
18650 numEscapeFn = function(match, capture) {\r
18651 return '\\00' + capture.charCodeAt(0).toString(16) + ' ';\r
18652 };\r
18653 return function(id) {\r
18654 return validIdRe.test(id) ? id : // replace the number portion last to keep the trailing ' '\r
18655 // from being escaped\r
18656 id.replace(escapeRx, escapeFn).replace(leadingNumRx, numEscapeFn);\r
18657 };\r
18658 }()),\r
18659 /**
18660 * @method callback
18661 * @member Ext
18662 * Execute a callback function in a particular scope. If `callback` argument is a
18663 * function reference, that is called. If it is a string, the string is assumed to
18664 * be the name of a method on the given `scope`. If no function is passed the call
18665 * is ignored.
18666 *
18667 * For example, these calls are equivalent:
18668 *
18669 * var myFunc = this.myFunc;
18670 *
18671 * Ext.callback('myFunc', this, [arg1, arg2]);
18672 * Ext.callback(myFunc, this, [arg1, arg2]);
18673 *
18674 * Ext.isFunction(myFunc) && this.myFunc(arg1, arg2);
18675 *
18676 * @param {Function/String} callback The callback function to execute or the name of
18677 * the callback method on the provided `scope`.
18678 * @param {Object} [scope] The scope in which `callback` should be invoked. If `callback`
18679 * is a string this object provides the method by that name. If this is `null` then
18680 * the `caller` is used to resolve the scope to a `ViewController` or the proper
18681 * `defaultListenerScope`.
18682 * @param {Array} [args] The arguments to pass to the function.
18683 * @param {Number} [delay] Pass a number to delay the call by a number of milliseconds.
18684 * @param {Object} [caller] The object calling the callback. This is used to resolve
18685 * named methods when no explicit `scope` is provided.
18686 * @param {Object} [defaultScope=caller] The default scope to return if none is found.
18687 * @return The value returned by the callback or `undefined` (if there is a `delay`
18688 * or if the `callback` is not a function).
18689 */\r
18690 callback: function(callback, scope, args, delay, caller, defaultScope) {\r
18691 if (!callback) {\r
18692 return;\r
18693 }\r
18694 var namedScope = (scope in Ext._namedScopes);\r
18695 if (callback.charAt) {\r
18696 // if (isString(fn))\r
18697 if ((!scope || namedScope) && caller) {\r
18698 scope = caller.resolveListenerScope(namedScope ? scope : defaultScope);\r
18699 }\r
18700 if (!scope || !Ext.isObject(scope)) {\r
18701 Ext.raise('Named method "' + callback + '" requires a scope object');\r
18702 }\r
18703 if (!Ext.isFunction(scope[callback])) {\r
18704 Ext.raise('No method named "' + callback + '" on ' + (scope.$className || 'scope object'));\r
18705 }\r
18706 callback = scope[callback];\r
18707 } else if (namedScope) {\r
18708 scope = defaultScope || caller;\r
18709 } else if (!scope) {\r
18710 scope = caller;\r
18711 }\r
18712 var ret;\r
18713 if (callback && Ext.isFunction(callback)) {\r
18714 scope = scope || Ext.global;\r
18715 if (delay) {\r
18716 Ext.defer(callback, delay, scope, args);\r
18717 } else if (Ext.elevateFunction) {\r
18718 ret = Ext.elevateFunction(callback, scope, args);\r
18719 } else if (args) {\r
18720 ret = callback.apply(scope, args);\r
18721 } else {\r
18722 ret = callback.call(scope);\r
18723 }\r
18724 }\r
18725 return ret;\r
18726 },\r
18727 /**
18728 * @method coerce
18729 * @member Ext
18730 * Coerces the first value if possible so that it is comparable to the second value.
18731 *
18732 * Coercion only works between the basic atomic data types String, Boolean, Number, Date, null and undefined.
18733 *
18734 * Numbers and numeric strings are coerced to Dates using the value as the millisecond era value.
18735 *
18736 * Strings are coerced to Dates by parsing using the {@link Ext.Date#defaultFormat defaultFormat}.
18737 *
18738 * For example
18739 *
18740 * Ext.coerce('false', true);
18741 *
18742 * returns the boolean value `false` because the second parameter is of type `Boolean`.
18743 *
18744 * @param {Mixed} from The value to coerce
18745 * @param {Mixed} to The value it must be compared against
18746 * @return The coerced value.
18747 */\r
18748 coerce: function(from, to) {\r
18749 var fromType = Ext.typeOf(from),\r
18750 toType = Ext.typeOf(to),\r
18751 isString = typeof from === 'string';\r
18752 if (fromType !== toType) {\r
18753 switch (toType) {\r
18754 case 'string':\r
18755 return String(from);\r
18756 case 'number':\r
18757 return Number(from);\r
18758 case 'boolean':\r
18759 return isString && (!from || from === 'false') ? false : Boolean(from);\r
18760 case 'null':\r
18761 return isString && (!from || from === 'null') ? null : from;\r
18762 case 'undefined':\r
18763 return isString && (!from || from === 'undefined') ? undefined : from;\r
18764 case 'date':\r
18765 return isString && isNaN(from) ? Ext.Date.parse(from, Ext.Date.defaultFormat) : Date(Number(from));\r
18766 }\r
18767 }\r
18768 return from;\r
18769 },\r
18770 /**
18771 * @method copyTo
18772 * @member Ext
18773 * Copies a set of named properties fom the source object to the destination object.
18774 *
18775 * Example:
18776 *
18777 * var foo = { a: 1, b: 2, c: 3 };
18778 *
18779 * var bar = Ext.copyTo({}, foo, 'a,c');
18780 * // bar = { a: 1, c: 3 };
18781 *
18782 * Important note: To borrow class prototype methods, use {@link Ext.Base#borrow} instead.
18783 *
18784 * @param {Object} dest The destination object.
18785 * @param {Object} source The source object.
18786 * @param {String/String[]} names Either an Array of property names, or a comma-delimited list
18787 * of property names to copy.
18788 * @param {Boolean} [usePrototypeKeys=false] Pass `true` to copy keys off of the
18789 * prototype as well as the instance.
18790 * @return {Object} The `dest` object.
18791 * @deprecated 6.0.1 Use {@link Ext#copy Ext.copy} instead. This old method
18792 * would copy the named preoperties even if they did not exist in the source which
18793 * could produce `undefined` values in the destination.
18794 */\r
18795 copyTo: function(dest, source, names, usePrototypeKeys) {\r
18796 if (typeof names === 'string') {\r
18797 names = names.split(Ext.propertyNameSplitRe);\r
18798 }\r
18799 for (var name,\r
18800 i = 0,\r
18801 n = names ? names.length : 0; i < n; i++) {\r
18802 name = names[i];\r
18803 if (usePrototypeKeys || source.hasOwnProperty(name)) {\r
18804 dest[name] = source[name];\r
18805 }\r
18806 }\r
18807 return dest;\r
18808 },\r
18809 /**
18810 * @method copy
18811 * @member Ext
18812 * Copies a set of named properties fom the source object to the destination object.
18813 *
18814 * Example:
18815 *
18816 * var foo = { a: 1, b: 2, c: 3 };
18817 *
18818 * var bar = Ext.copy({}, foo, 'a,c');
18819 * // bar = { a: 1, c: 3 };
18820 *
18821 * Important note: To borrow class prototype methods, use {@link Ext.Base#borrow} instead.
18822 *
18823 * @param {Object} dest The destination object.
18824 * @param {Object} source The source object.
18825 * @param {String/String[]} names Either an Array of property names, or a comma-delimited list
18826 * of property names to copy.
18827 * @param {Boolean} [usePrototypeKeys=false] Pass `true` to copy keys off of the
18828 * prototype as well as the instance.
18829 * @return {Object} The `dest` object.
18830 */\r
18831 copy: function(dest, source, names, usePrototypeKeys) {\r
18832 if (typeof names === 'string') {\r
18833 names = names.split(Ext.propertyNameSplitRe);\r
18834 }\r
18835 for (var name,\r
18836 i = 0,\r
18837 n = names ? names.length : 0; i < n; i++) {\r
18838 name = names[i];\r
18839 // Only copy a property if the source actually *has* that property.\r
18840 // If we are including prototype properties, then ensure that a property of\r
18841 // that name can be found *somewhere* in the prototype chain (otherwise we'd be copying undefined in which may break things)\r
18842 if (source.hasOwnProperty(name) || (usePrototypeKeys && name in source)) {\r
18843 dest[name] = source[name];\r
18844 }\r
18845 }\r
18846 return dest;\r
18847 },\r
18848 propertyNameSplitRe: /[,;\s]+/,\r
18849 /**
18850 * @method copyToIf
18851 * @member Ext
18852 * Copies a set of named properties fom the source object to the destination object
18853 * if the destination object does not already have them.
18854 *
18855 * Example:
18856 *
18857 * var foo = { a: 1, b: 2, c: 3 };
18858 *
18859 * var bar = Ext.copyToIf({ a:42 }, foo, 'a,c');
18860 * // bar = { a: 42, c: 3 };
18861 *
18862 * @param {Object} destination The destination object.
18863 * @param {Object} source The source object.
18864 * @param {String/String[]} names Either an Array of property names, or a single string
18865 * with a list of property names separated by ",", ";" or spaces.
18866 * @return {Object} The `dest` object.
18867 * @deprecated 6.0.1 Use {@link Ext#copyIf Ext.copyIf} instead. This old method
18868 * would copy the named preoperties even if they did not exist in the source which
18869 * could produce `undefined` values in the destination.
18870 */\r
18871 copyToIf: function(destination, source, names) {\r
18872 if (typeof names === 'string') {\r
18873 names = names.split(Ext.propertyNameSplitRe);\r
18874 }\r
18875 for (var name,\r
18876 i = 0,\r
18877 n = names ? names.length : 0; i < n; i++) {\r
18878 name = names[i];\r
18879 if (destination[name] === undefined) {\r
18880 destination[name] = source[name];\r
18881 }\r
18882 }\r
18883 return destination;\r
18884 },\r
18885 /**
18886 * @method copyIf
18887 * @member Ext
18888 * Copies a set of named properties fom the source object to the destination object
18889 * if the destination object does not already have them.
18890 *
18891 * Example:
18892 *
18893 * var foo = { a: 1, b: 2, c: 3 };
18894 *
18895 * var bar = Ext.copyIf({ a:42 }, foo, 'a,c');
18896 * // bar = { a: 42, c: 3 };
18897 *
18898 * @param {Object} destination The destination object.
18899 * @param {Object} source The source object.
18900 * @param {String/String[]} names Either an Array of property names, or a single string
18901 * with a list of property names separated by ",", ";" or spaces.
18902 * @return {Object} The `dest` object.
18903 */\r
18904 copyIf: function(destination, source, names) {\r
18905 if (typeof names === 'string') {\r
18906 names = names.split(Ext.propertyNameSplitRe);\r
18907 }\r
18908 for (var name,\r
18909 i = 0,\r
18910 n = names ? names.length : 0; i < n; i++) {\r
18911 name = names[i];\r
18912 // Only copy a property if the destination has no property by that name\r
18913 if (!(name in destination) && (name in source)) {\r
18914 destination[name] = source[name];\r
18915 }\r
18916 }\r
18917 return destination;\r
18918 },\r
18919 /**
18920 * @method extend
18921 * @member Ext
18922 * This method deprecated. Use {@link Ext#define Ext.define} instead.
18923 * @param {Function} superclass
18924 * @param {Object} overrides
18925 * @return {Function} The subclass constructor from the <tt>overrides</tt> parameter, or a generated one if not provided.
18926 * @deprecated 4.0.0 Use {@link Ext#define Ext.define} instead
18927 */\r
18928 extend: (function() {\r
18929 // inline overrides\r
18930 var objectConstructor = Object.prototype.constructor,\r
18931 inlineOverrides = function(o) {\r
18932 for (var m in o) {\r
18933 if (!o.hasOwnProperty(m)) {\r
18934 \r
18935 continue;\r
18936 }\r
18937 this[m] = o[m];\r
18938 }\r
18939 };\r
18940 return function(subclass, superclass, overrides) {\r
18941 // First we check if the user passed in just the superClass with overrides\r
18942 if (Ext.isObject(superclass)) {\r
18943 overrides = superclass;\r
18944 superclass = subclass;\r
18945 subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {\r
18946 superclass.apply(this, arguments);\r
18947 };\r
18948 }\r
18949 if (!superclass) {\r
18950 Ext.raise({\r
18951 sourceClass: 'Ext',\r
18952 sourceMethod: 'extend',\r
18953 msg: 'Attempting to extend from a class which has not been loaded on the page.'\r
18954 });\r
18955 }\r
18956 // We create a new temporary class\r
18957 var F = function() {},\r
18958 subclassProto,\r
18959 superclassProto = superclass.prototype;\r
18960 F.prototype = superclassProto;\r
18961 subclassProto = subclass.prototype = new F();\r
18962 subclassProto.constructor = subclass;\r
18963 subclass.superclass = superclassProto;\r
18964 if (superclassProto.constructor === objectConstructor) {\r
18965 superclassProto.constructor = superclass;\r
18966 }\r
18967 subclass.override = function(overrides) {\r
18968 Ext.override(subclass, overrides);\r
18969 };\r
18970 subclassProto.override = inlineOverrides;\r
18971 subclassProto.proto = subclassProto;\r
18972 subclass.override(overrides);\r
18973 subclass.extend = function(o) {\r
18974 return Ext.extend(subclass, o);\r
18975 };\r
18976 return subclass;\r
18977 };\r
18978 }()),\r
18979 /**
18980 * @method iterate
18981 * @member Ext
18982 * Iterates either an array or an object. This method delegates to
18983 * {@link Ext.Array#each Ext.Array.each} if the given value is iterable, and {@link Ext.Object#each Ext.Object.each} otherwise.
18984 *
18985 * @param {Object/Array} object The object or array to be iterated.
18986 * @param {Function} fn The function to be called for each iteration. See and {@link Ext.Array#each Ext.Array.each} and
18987 * {@link Ext.Object#each Ext.Object.each} for detailed lists of arguments passed to this function depending on the given object
18988 * type that is being iterated.
18989 * @param {Object} [scope] The scope (`this` reference) in which the specified function is executed.
18990 * Defaults to the object being iterated itself.
18991 */\r
18992 iterate: function(object, fn, scope) {\r
18993 if (Ext.isEmpty(object)) {\r
18994 return;\r
18995 }\r
18996 if (scope === undefined) {\r
18997 scope = object;\r
18998 }\r
18999 if (Ext.isIterable(object)) {\r
19000 Ext.Array.each.call(Ext.Array, object, fn, scope);\r
19001 } else {\r
19002 Ext.Object.each.call(Ext.Object, object, fn, scope);\r
19003 }\r
19004 },\r
19005 _resourcePoolRe: /^[<]([^<>@:]*)(?:[@]([^<>@:]+))?[>](.+)$/,\r
19006 /**
19007 * Resolves a resource URL that may contain a resource pool identifier token at the
19008 * front. The tokens are formatted as HTML tags "&lt;poolName@packageName&gt;" followed
19009 * by a normal relative path. This token is only processed if present at the first
19010 * character of the given string.
19011 *
19012 * These tokens are parsed and the pieces are then passed to the
19013 * {@link Ext#getResourcePath} method.
19014 *
19015 * For example:
19016 *
19017 * [{
19018 * xtype: 'image',
19019 * src: '<shared>images/foo.png'
19020 * },{
19021 * xtype: 'image',
19022 * src: '<@package>images/foo.png'
19023 * },{
19024 * xtype: 'image',
19025 * src: '<shared@package>images/foo.png'
19026 * }]
19027 *
19028 * In the above example, "shared" is the name of a Sencha Cmd resource pool and
19029 * "package" is the name of a Sencha Cmd package.
19030 *
19031 * @param {String} url The URL that may contain a resource pool token at the front.
19032 * @return {String}
19033 * @since 6.0.1
19034 */\r
19035 resolveResource: function(url) {\r
19036 var ret = url,\r
19037 m;\r
19038 if (url && url.charAt(0) === '<') {\r
19039 m = Ext._resourcePoolRe.exec(url);\r
19040 if (m) {\r
19041 ret = Ext.getResourcePath(m[3], m[1], m[2]);\r
19042 }\r
19043 }\r
19044 return ret;\r
19045 },\r
19046 /**
19047 *
19048 * @member Ext
19049 * @method urlEncode
19050 * @inheritdoc Ext.Object#toQueryString
19051 * @deprecated 4.0.0 Use {@link Ext.Object#toQueryString} instead
19052 */\r
19053 urlEncode: function() {\r
19054 var args = Ext.Array.from(arguments),\r
19055 prefix = '';\r
19056 // Support for the old `pre` argument\r
19057 if (Ext.isString(args[1])) {\r
19058 prefix = args[1] + '&';\r
19059 args[1] = false;\r
19060 }\r
19061 return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);\r
19062 },\r
19063 /**
19064 * Alias for {@link Ext.Object#fromQueryString}.
19065 *
19066 * @member Ext
19067 * @method urlDecode
19068 * @inheritdoc Ext.Object#fromQueryString
19069 * @deprecated 4.0.0 Use {@link Ext.Object#fromQueryString} instead
19070 */\r
19071 urlDecode: function() {\r
19072 return Ext.Object.fromQueryString.apply(Ext.Object, arguments);\r
19073 },\r
19074 /**
19075 * @method getScrollbarSize
19076 * @member Ext
19077 * Returns the size of the browser scrollbars. This can differ depending on
19078 * operating system settings, such as the theme or font size.
19079 * @param {Boolean} [force] true to force a recalculation of the value.
19080 * @return {Object} An object containing scrollbar sizes.
19081 * @return {Number} return.width The width of the vertical scrollbar.
19082 * @return {Number} return.height The height of the horizontal scrollbar.
19083 */\r
19084 getScrollbarSize: function(force) {\r
19085 if (!Ext.isDomReady) {\r
19086 Ext.raise("getScrollbarSize called before DomReady");\r
19087 }\r
19088 var scrollbarSize = Ext._scrollbarSize;\r
19089 if (force || !scrollbarSize) {\r
19090 var db = document.body,\r
19091 div = document.createElement('div');\r
19092 div.style.width = div.style.height = '100px';\r
19093 div.style.overflow = 'scroll';\r
19094 div.style.position = 'absolute';\r
19095 db.appendChild(div);\r
19096 // now we can measure the div...\r
19097 // at least in iE9 the div is not 100px - the scrollbar size is removed!\r
19098 Ext._scrollbarSize = scrollbarSize = {\r
19099 width: div.offsetWidth - div.clientWidth,\r
19100 height: div.offsetHeight - div.clientHeight\r
19101 };\r
19102 db.removeChild(div);\r
19103 }\r
19104 return scrollbarSize;\r
19105 },\r
19106 /**
19107 * @method typeOf
19108 * @member Ext
19109 * Returns the type of the given variable in string format. List of possible values are:
19110 *
19111 * - `undefined`: If the given value is `undefined`
19112 * - `null`: If the given value is `null`
19113 * - `string`: If the given value is a string
19114 * - `number`: If the given value is a number
19115 * - `boolean`: If the given value is a boolean value
19116 * - `date`: If the given value is a `Date` object
19117 * - `function`: If the given value is a function reference
19118 * - `object`: If the given value is an object
19119 * - `array`: If the given value is an array
19120 * - `regexp`: If the given value is a regular expression
19121 * - `element`: If the given value is a DOM Element
19122 * - `textnode`: If the given value is a DOM text node and contains something other than whitespace
19123 * - `whitespace`: If the given value is a DOM text node and contains only whitespace
19124 *
19125 * @param {Object} value
19126 * @return {String}
19127 */\r
19128 typeOf: (function() {\r
19129 var nonWhitespaceRe = /\S/,\r
19130 toString = Object.prototype.toString,\r
19131 typeofTypes = {\r
19132 number: 1,\r
19133 string: 1,\r
19134 'boolean': 1,\r
19135 'undefined': 1\r
19136 },\r
19137 toStringTypes = {\r
19138 '[object Array]': 'array',\r
19139 '[object Date]': 'date',\r
19140 '[object Boolean]': 'boolean',\r
19141 '[object Number]': 'number',\r
19142 '[object RegExp]': 'regexp'\r
19143 };\r
19144 return function(value) {\r
19145 if (value === null) {\r
19146 return 'null';\r
19147 }\r
19148 var type = typeof value,\r
19149 ret, typeToString;\r
19150 if (typeofTypes[type]) {\r
19151 return type;\r
19152 }\r
19153 ret = toStringTypes[typeToString = toString.call(value)];\r
19154 if (ret) {\r
19155 return ret;\r
19156 }\r
19157 if (type === 'function') {\r
19158 return 'function';\r
19159 }\r
19160 if (type === 'object') {\r
19161 if (value.nodeType !== undefined) {\r
19162 if (value.nodeType === 3) {\r
19163 return nonWhitespaceRe.test(value.nodeValue) ? 'textnode' : 'whitespace';\r
19164 } else {\r
19165 return 'element';\r
19166 }\r
19167 }\r
19168 return 'object';\r
19169 }\r
19170 Ext.raise({\r
19171 sourceClass: 'Ext',\r
19172 sourceMethod: 'typeOf',\r
19173 msg: 'Failed to determine the type of "' + value + '".'\r
19174 });\r
19175 return typeToString;\r
19176 };\r
19177 }()),\r
19178 /**
19179 * A global factory method to instantiate a class from a config object. For example,
19180 * these two calls are equivalent:
19181 *
19182 * Ext.factory({ text: 'My Button' }, 'Ext.Button');
19183 * Ext.create('Ext.Button', { text: 'My Button' });
19184 *
19185 * If an existing instance is also specified, it will be updated with the supplied config object. This is useful
19186 * if you need to either create or update an object, depending on if an instance already exists. For example:
19187 *
19188 * var button;
19189 * button = Ext.factory({ text: 'New Button' }, 'Ext.Button', button); // Button created
19190 * button = Ext.factory({ text: 'Updated Button' }, 'Ext.Button', button); // Button updated
19191 *
19192 * @param {Object} config The config object to instantiate or update an instance with.
19193 * @param {String} [classReference] The class to instantiate from (if there is a default).
19194 * @param {Object} [instance] The instance to update.
19195 * @param [aliasNamespace]
19196 * @member Ext
19197 */\r
19198 factory: function(config, classReference, instance, aliasNamespace) {\r
19199 var manager = Ext.ClassManager,\r
19200 newInstance;\r
19201 // If config is falsy or a valid instance, destroy the current instance\r
19202 // (if it exists) and replace with the new one\r
19203 if (!config || config.isInstance) {\r
19204 if (instance && instance !== config) {\r
19205 instance.destroy();\r
19206 }\r
19207 return config;\r
19208 }\r
19209 if (aliasNamespace) {\r
19210 // If config is a string value, treat it as an alias\r
19211 if (typeof config === 'string') {\r
19212 return manager.instantiateByAlias(aliasNamespace + '.' + config);\r
19213 }\r
19214 // Same if 'type' is given in config\r
19215 else if (Ext.isObject(config) && 'type' in config) {\r
19216 return manager.instantiateByAlias(aliasNamespace + '.' + config.type, config);\r
19217 }\r
19218 }\r
19219 if (config === true) {\r
19220 if (!instance && !classReference) {\r
19221 Ext.raise('[Ext.factory] Cannot determine type of class to create');\r
19222 }\r
19223 return instance || Ext.create(classReference);\r
19224 }\r
19225 if (!Ext.isObject(config)) {\r
19226 Ext.raise("Invalid config, must be a valid config object");\r
19227 }\r
19228 if ('xtype' in config) {\r
19229 newInstance = manager.instantiateByAlias('widget.' + config.xtype, config);\r
19230 } else if ('xclass' in config) {\r
19231 newInstance = Ext.create(config.xclass, config);\r
19232 }\r
19233 if (newInstance) {\r
19234 if (instance) {\r
19235 instance.destroy();\r
19236 }\r
19237 return newInstance;\r
19238 }\r
19239 if (instance) {\r
19240 return instance.setConfig(config);\r
19241 }\r
19242 return Ext.create(classReference, config);\r
19243 },\r
19244 /**
19245 * @method log
19246 * @member Ext
19247 * Logs a message. If a console is present it will be used. On Opera, the method
19248 * "opera.postError" is called. In other cases, the message is logged to an array
19249 * "Ext.log.out". An attached debugger can watch this array and view the log. The
19250 * log buffer is limited to a maximum of "Ext.log.max" entries (defaults to 250).
19251 *
19252 * If additional parameters are passed, they are joined and appended to the message.
19253 * A technique for tracing entry and exit of a function is this:
19254 *
19255 * function foo () {
19256 * Ext.log({ indent: 1 }, '>> foo');
19257 *
19258 * // log statements in here or methods called from here will be indented
19259 * // by one step
19260 *
19261 * Ext.log({ outdent: 1 }, '<< foo');
19262 * }
19263 *
19264 * This method does nothing in a release build.
19265 *
19266 * @param {String/Object} [options] The message to log or an options object with any
19267 * of the following properties:
19268 *
19269 * - `msg`: The message to log (required).
19270 * - `level`: One of: "error", "warn", "info" or "log" (the default is "log").
19271 * - `dump`: An object to dump to the log as part of the message.
19272 * - `stack`: True to include a stack trace in the log.
19273 * - `indent`: Cause subsequent log statements to be indented one step.
19274 * - `outdent`: Cause this and following statements to be one step less indented.
19275 *
19276 * @param {String...} [message] The message to log (required unless specified in
19277 * options object).
19278 */\r
19279 log: (function() {\r
19280 /*
19281 * Iterate through an object to dump its content into a string.
19282 * For example:
19283 * {
19284 * style: {
19285 * lineWidth: 1
19286 * },
19287 * label: {},
19288 * marker: {
19289 * strokeStyle: "#555",
19290 * radius: 3,
19291 * size: 3
19292 * },
19293 * subStyle: {
19294 * fillStyle: [
19295 * 0: "#133987",
19296 * 1: "#1c55ca",
19297 * 2: "#4d7fe6"
19298 * ]
19299 * },
19300 * markerSubStyle: {}
19301 * }
19302 *
19303 * @param {Object} object The object to iterate
19304 * @param {Number} [level] Current level of identation (and recursion). Default is 0.
19305 * @param {Number} [maxLevel] Maximum level of recursion. Default is 3.
19306 * @param {Boolean} [withFunctions] Include functions in the output.
19307 * @return {String} The string with the contents of the object
19308 */\r
19309 var primitiveRe = /string|number|boolean/;\r
19310 function dumpObject(object, level, maxLevel, withFunctions) {\r
19311 var member, type, value, name, prefix, suffix,\r
19312 members = [];\r
19313 if (Ext.isArray(object)) {\r
19314 prefix = '[';\r
19315 suffix = ']';\r
19316 } else if (Ext.isObject(object)) {\r
19317 prefix = '{';\r
19318 suffix = '}';\r
19319 }\r
19320 if (!maxLevel) {\r
19321 maxLevel = 3;\r
19322 }\r
19323 if (level > maxLevel) {\r
19324 return prefix + '...' + suffix;\r
19325 }\r
19326 level = level || 1;\r
19327 var spacer = (new Array(level)).join(' ');\r
19328 // Cannot use Ext.encode since it can recurse endlessly\r
19329 for (name in object) {\r
19330 if (object.hasOwnProperty(name)) {\r
19331 value = object[name];\r
19332 type = typeof value;\r
19333 if (type === 'function') {\r
19334 if (!withFunctions) {\r
19335 \r
19336 continue;\r
19337 }\r
19338 member = type;\r
19339 } else if (type === 'undefined') {\r
19340 member = type;\r
19341 } else if (value === null || primitiveRe.test(type) || Ext.isDate(value)) {\r
19342 member = Ext.encode(value);\r
19343 } else if (Ext.isArray(value)) {\r
19344 member = dumpObject(value, level + 1, maxLevel, withFunctions);\r
19345 } else if (Ext.isObject(value)) {\r
19346 member = dumpObject(value, level + 1, maxLevel, withFunctions);\r
19347 } else {\r
19348 member = type;\r
19349 }\r
19350 members.push(spacer + name + ': ' + member);\r
19351 }\r
19352 }\r
19353 // or Ext.encode(name)\r
19354 if (members.length) {\r
19355 return prefix + '\n ' + members.join(',\n ') + '\n' + spacer + suffix;\r
19356 }\r
19357 return prefix + suffix;\r
19358 }\r
19359 function log(message) {\r
19360 var options, dump,\r
19361 con = Ext.global.console,\r
19362 level = 'log',\r
19363 indent = log.indent || 0,\r
19364 prefix, stack, fn, out, max;\r
19365 log.indent = indent;\r
19366 if (typeof message !== 'string') {\r
19367 options = message;\r
19368 message = options.msg || '';\r
19369 level = options.level || level;\r
19370 dump = options.dump;\r
19371 stack = options.stack;\r
19372 prefix = options.prefix;\r
19373 fn = options.fn;\r
19374 if (options.indent) {\r
19375 ++log.indent;\r
19376 } else if (options.outdent) {\r
19377 log.indent = indent = Math.max(indent - 1, 0);\r
19378 }\r
19379 if (dump && !(con && con.dir)) {\r
19380 message += dumpObject(dump);\r
19381 dump = null;\r
19382 }\r
19383 }\r
19384 if (arguments.length > 1) {\r
19385 message += Array.prototype.slice.call(arguments, 1).join('');\r
19386 }\r
19387 if (prefix) {\r
19388 message = prefix + ' - ' + message;\r
19389 }\r
19390 message = indent ? Ext.String.repeat(' ', log.indentSize * indent) + message : message;\r
19391 // w/o console, all messages are equal, so munge the level into the message:\r
19392 if (level !== 'log') {\r
19393 message = '[' + level.charAt(0).toUpperCase() + '] ' + message;\r
19394 }\r
19395 if (fn) {\r
19396 message += '\nCaller: ' + fn.toString();\r
19397 }\r
19398 // Not obvious, but 'console' comes and goes when Firebug is turned on/off, so\r
19399 // an early test may fail either direction if Firebug is toggled.\r
19400 //\r
19401 if (con) {\r
19402 // if (Firebug-like console)\r
19403 if (con[level]) {\r
19404 con[level](message);\r
19405 } else {\r
19406 con.log(message);\r
19407 }\r
19408 if (dump) {\r
19409 con.dir(dump);\r
19410 }\r
19411 if (stack && con.trace) {\r
19412 // Firebug's console.error() includes a trace already...\r
19413 if (!con.firebug || level !== 'error') {\r
19414 con.trace();\r
19415 }\r
19416 }\r
19417 } else if (Ext.isOpera) {\r
19418 opera.postError(message);\r
19419 } else // jshint ignore:line\r
19420 {\r
19421 out = log.out;\r
19422 max = log.max;\r
19423 if (out.length >= max) {\r
19424 // this formula allows out.max to change (via debugger), where the\r
19425 // more obvious "max/4" would not quite be the same\r
19426 Ext.Array.erase(out, 0, out.length - 3 * Math.floor(max / 4));\r
19427 }\r
19428 // keep newest 75%\r
19429 out.push(message);\r
19430 }\r
19431 // Mostly informational, but the Ext.Error notifier uses them:\r
19432 ++log.count;\r
19433 ++log.counters[level];\r
19434 }\r
19435 function logx(level, args) {\r
19436 if (typeof args[0] === 'string') {\r
19437 args.unshift({});\r
19438 }\r
19439 args[0].level = level;\r
19440 log.apply(this, args);\r
19441 }\r
19442 log.error = function() {\r
19443 logx('error', Array.prototype.slice.call(arguments));\r
19444 };\r
19445 log.info = function() {\r
19446 logx('info', Array.prototype.slice.call(arguments));\r
19447 };\r
19448 log.warn = function() {\r
19449 logx('warn', Array.prototype.slice.call(arguments));\r
19450 };\r
19451 log.count = 0;\r
19452 log.counters = {\r
19453 error: 0,\r
19454 warn: 0,\r
19455 info: 0,\r
19456 log: 0\r
19457 };\r
19458 log.indentSize = 2;\r
19459 log.out = [];\r
19460 log.max = 750;\r
19461 return log;\r
19462 }()) || (function() {\r
19463 var nullLog = function() {};\r
19464 nullLog.info = nullLog.warn = nullLog.error = Ext.emptyFn;\r
19465 return nullLog;\r
19466 }())\r
19467});\r
19468\r
19469/**
19470 * @class Ext.Version
19471 *
19472 * A utility class that wraps around a version number string and provides convenient methods
19473 * to perform comparisons. A version number is expressed in the following general format:
19474 *
19475 * major[.minor[.patch[.build[release]]]]
19476 *
19477 * The `Version` instance holds various readonly properties that contain the digested form
19478 * of the version string. The numeric componnets of `major`, `minor`, `patch` and `build`
19479 * as well as the textual suffix called `release`.
19480 *
19481 * Not depicted in the above syntax are three possible prefixes used to control partial
19482 * matching. These are '^' (the default), '>' and '~'. These are discussed below.
19483 *
19484 * Examples:
19485 *
19486 * var version = new Ext.Version('1.0.2beta'); // or maybe "1.0" or "1.2.3.4RC"
19487 * console.log("Version is " + version); // Version is 1.0.2beta
19488 *
19489 * console.log(version.getMajor()); // 1
19490 * console.log(version.getMinor()); // 0
19491 * console.log(version.getPatch()); // 2
19492 * console.log(version.getBuild()); // 0
19493 * console.log(version.getRelease()); // beta
19494 *
19495 * The understood values of `release` are assigned numberic equivalents for the sake of
19496 * comparsion. The order of these from smallest to largest is as follows:
19497 *
19498 * * `"dev"`
19499 * * `"alpha"` or `"a"`
19500 * * `"beta"` or `"b"`
19501 * * `"RC"` or `"rc"`
19502 * * `"#"`
19503 * * `"pl"` or `"p"`
19504 *
19505 * Any other (unrecognized) suffix is consider greater than any of these.
19506 *
19507 * ## Comparisons
19508 * There are two forms of comparison that are commonly needed: full and partial. Full
19509 * comparison is simpler and is also the default.
19510 *
19511 * Example:
19512 *
19513 * var version = new Ext.Version('1.0.2beta');
19514 *
19515 * console.log(version.isGreaterThan('1.0.1')); // True
19516 * console.log(version.isGreaterThan('1.0.2alpha')); // True
19517 * console.log(version.isGreaterThan('1.0.2RC')); // False
19518 * console.log(version.isGreaterThan('1.0.2')); // False
19519 * console.log(version.isLessThan('1.0.2')); // True
19520 *
19521 * console.log(version.match(1.0)); // True (using a Number)
19522 * console.log(version.match('1.0.2')); // True (using a String)
19523 *
19524 * These comparisons are ultimately implemented by {@link Ext.Version#compareTo compareTo}
19525 * which returns -1, 0 or 1 depending on whether the `Version' instance is less than, equal
19526 * to, or greater than the given "other" version.
19527 *
19528 * For example:
19529 *
19530 * var n = version.compareTo('1.0.1'); // == 1 (because 1.0.2beta > 1.0.1)
19531 *
19532 * n = version.compareTo('1.1'); // == -1
19533 * n = version.compareTo(version); // == 0
19534 *
19535 * ### Partial Comparisons
19536 * By default, unspecified version number fields are filled with 0. In other words, the
19537 * version number fields are 0-padded on the right or a "lower bound". This produces the
19538 * most commonly used forms of comparsion:
19539 *
19540 * var ver = new Version('4.2');
19541 *
19542 * n = ver.compareTo('4.2.1'); // == -1 (4.2 promotes to 4.2.0 and is less than 4.2.1)
19543 *
19544 * There are two other ways to interpret comparisons of versions of different length. The
19545 * first of these is to change the padding on the right to be a large number (scuh as
19546 * Infinity) instead of 0. This has the effect of making the version an upper bound. For
19547 * example:
19548 *
19549 * var ver = new Version('^4.2'); // NOTE: the '^' prefix used
19550 *
19551 * n = ver.compareTo('4.3'); // == -1 (less than 4.3)
19552 *
19553 * n = ver.compareTo('4.2'); // == 1 (greater than all 4.2's)
19554 * n = ver.compareTo('4.2.1'); // == 1
19555 * n = ver.compareTo('4.2.9'); // == 1
19556 *
19557 * The second way to interpret this comparison is to ignore the extra digits, making the
19558 * match a prefix match. For example:
19559 *
19560 * var ver = new Version('~4.2'); // NOTE: the '~' prefix used
19561 *
19562 * n = ver.compareTo('4.3'); // == -1
19563 *
19564 * n = ver.compareTo('4.2'); // == 0
19565 * n = ver.compareTo('4.2.1'); // == 0
19566 *
19567 * This final form can be useful when version numbers contain more components than are
19568 * important for certain comparisons. For example, the full version of Ext JS 4.2.1 is
19569 * "4.2.1.883" where 883 is the `build` number.
19570 *
19571 * This is how to create a "partial" `Version` and compare versions to it:
19572 *
19573 * var version421ish = new Version('~4.2.1');
19574 *
19575 * n = version421ish.compareTo('4.2.1.883'); // == 0
19576 * n = version421ish.compareTo('4.2.1.2'); // == 0
19577 * n = version421ish.compareTo('4.2.1'); // == 0
19578 *
19579 * n = version421ish.compareTo('4.2'); // == 1
19580 *
19581 * In the above example, '4.2.1.2' compares as equal to '4.2.1' because digits beyond the
19582 * given "4.2.1" are ignored. However, '4.2' is less than the '4.2.1' prefix; its missing
19583 * digit is filled with 0.
19584 */\r
19585(function() {\r
19586 // @define Ext.Version\r
19587 // @require Ext.String\r
19588 var // used by checkVersion to avoid temp arrays:\r
19589 checkVerTemp = [\r
19590 ''\r
19591 ],\r
19592 endOfVersionRe = /([^\d\.])/,\r
19593 notDigitsRe = /[^\d]/g,\r
19594 plusMinusRe = /[\-+]/g,\r
19595 stripRe = /\s/g,\r
19596 underscoreRe = /_/g,\r
19597 toolkitNames = {\r
19598 classic: 1,\r
19599 modern: 1\r
19600 },\r
19601 Version;\r
19602 Ext.Version = Version = function(version, defaultMode) {\r
19603 var me = this,\r
19604 padModes = me.padModes,\r
19605 ch, i, pad, parts, release, releaseStartIndex, ver;\r
19606 if (version.isVersion) {\r
19607 version = version.version;\r
19608 }\r
19609 me.version = ver = String(version).toLowerCase().replace(underscoreRe, '.').replace(plusMinusRe, '');\r
19610 ch = ver.charAt(0);\r
19611 if (ch in padModes) {\r
19612 ver = ver.substring(1);\r
19613 pad = padModes[ch];\r
19614 } else {\r
19615 pad = defaultMode ? padModes[defaultMode] : 0;\r
19616 }\r
19617 // careful - NaN is falsey!\r
19618 me.pad = pad;\r
19619 releaseStartIndex = ver.search(endOfVersionRe);\r
19620 me.shortVersion = ver;\r
19621 if (releaseStartIndex !== -1) {\r
19622 me.release = release = ver.substr(releaseStartIndex, version.length);\r
19623 me.shortVersion = ver.substr(0, releaseStartIndex);\r
19624 release = Version.releaseValueMap[release] || release;\r
19625 }\r
19626 me.releaseValue = release || pad;\r
19627 me.shortVersion = me.shortVersion.replace(notDigitsRe, '');\r
19628 /**
19629 * @property {Number[]} parts
19630 * The split array of version number components found in the version string.
19631 * For example, for "1.2.3", this would be `[1, 2, 3]`.
19632 * @readonly
19633 * @private
19634 */\r
19635 me.parts = parts = ver.split('.');\r
19636 for (i = parts.length; i--; ) {\r
19637 parts[i] = parseInt(parts[i], 10);\r
19638 }\r
19639 if (pad === Infinity) {\r
19640 // have to add this to the end to create an upper bound:\r
19641 parts.push(pad);\r
19642 }\r
19643 /**
19644 * @property {Number} major
19645 * The first numeric part of the version number string.
19646 * @readonly
19647 */\r
19648 me.major = parts[0] || pad;\r
19649 /**
19650 * @property {Number} [minor]
19651 * The second numeric part of the version number string.
19652 * @readonly
19653 */\r
19654 me.minor = parts[1] || pad;\r
19655 /**
19656 * @property {Number} [patch]
19657 * The third numeric part of the version number string.
19658 * @readonly
19659 */\r
19660 me.patch = parts[2] || pad;\r
19661 /**
19662 * @property {Number} [build]
19663 * The fourth numeric part of the version number string.
19664 * @readonly
19665 */\r
19666 me.build = parts[3] || pad;\r
19667 return me;\r
19668 };\r
19669 Version.prototype = {\r
19670 isVersion: true,\r
19671 padModes: {\r
19672 '~': NaN,\r
19673 '^': Infinity\r
19674 },\r
19675 /**
19676 * @property {String} [release=""]
19677 * The release level. The following values are understood:
19678 *
19679 * * `"dev"`
19680 * * `"alpha"` or `"a"`
19681 * * `"beta"` or `"b"`
19682 * * `"RC"` or `"rc"`
19683 * * `"#"`
19684 * * `"pl"` or `"p"`
19685 * @readonly
19686 */\r
19687 release: '',\r
19688 /**
19689 * Compares this version instance to the specified `other` version.
19690 *
19691 * @param {String/Number/Ext.Version} other The other version to which to compare.
19692 * @return {Number} -1 if this version is less than the target version, 1 if this
19693 * version is greater, and 0 if they are equal.
19694 */\r
19695 compareTo: function(other) {\r
19696 // "lhs" == "left-hand-side"\r
19697 // "rhs" == "right-hand-side"\r
19698 var me = this,\r
19699 lhsPad = me.pad,\r
19700 lhsParts = me.parts,\r
19701 lhsLength = lhsParts.length,\r
19702 rhsVersion = other.isVersion ? other : new Version(other),\r
19703 rhsPad = rhsVersion.pad,\r
19704 rhsParts = rhsVersion.parts,\r
19705 rhsLength = rhsParts.length,\r
19706 length = Math.max(lhsLength, rhsLength),\r
19707 i, lhs, rhs;\r
19708 for (i = 0; i < length; i++) {\r
19709 lhs = (i < lhsLength) ? lhsParts[i] : lhsPad;\r
19710 rhs = (i < rhsLength) ? rhsParts[i] : rhsPad;\r
19711 // When one or both of the values are NaN these tests produce false\r
19712 // and we end up treating NaN as equal to anything.\r
19713 if (lhs < rhs) {\r
19714 return -1;\r
19715 }\r
19716 if (lhs > rhs) {\r
19717 return 1;\r
19718 }\r
19719 }\r
19720 // same comments about NaN apply here...\r
19721 lhs = me.releaseValue;\r
19722 rhs = rhsVersion.releaseValue;\r
19723 if (lhs < rhs) {\r
19724 return -1;\r
19725 }\r
19726 if (lhs > rhs) {\r
19727 return 1;\r
19728 }\r
19729 return 0;\r
19730 },\r
19731 /**
19732 * Override the native `toString` method
19733 * @private
19734 * @return {String} version
19735 */\r
19736 toString: function() {\r
19737 return this.version;\r
19738 },\r
19739 /**
19740 * Override the native `valueOf` method
19741 * @private
19742 * @return {String} version
19743 */\r
19744 valueOf: function() {\r
19745 return this.version;\r
19746 },\r
19747 /**
19748 * Returns the major component value.
19749 * @return {Number}
19750 */\r
19751 getMajor: function() {\r
19752 return this.major;\r
19753 },\r
19754 /**
19755 * Returns the minor component value.
19756 * @return {Number}
19757 */\r
19758 getMinor: function() {\r
19759 return this.minor;\r
19760 },\r
19761 /**
19762 * Returns the patch component value.
19763 * @return {Number}
19764 */\r
19765 getPatch: function() {\r
19766 return this.patch;\r
19767 },\r
19768 /**
19769 * Returns the build component value.
19770 * @return {Number}
19771 */\r
19772 getBuild: function() {\r
19773 return this.build;\r
19774 },\r
19775 /**
19776 * Returns the release component text (e.g., "beta").
19777 * @return {String}
19778 */\r
19779 getRelease: function() {\r
19780 return this.release;\r
19781 },\r
19782 /**
19783 * Returns the release component value for comparison purposes.
19784 * @return {Number/String}
19785 */\r
19786 getReleaseValue: function() {\r
19787 return this.releaseValue;\r
19788 },\r
19789 /**
19790 * Returns whether this version if greater than the supplied argument
19791 * @param {String/Number} target The version to compare with
19792 * @return {Boolean} `true` if this version if greater than the target, `false` otherwise
19793 */\r
19794 isGreaterThan: function(target) {\r
19795 return this.compareTo(target) > 0;\r
19796 },\r
19797 /**
19798 * Returns whether this version if greater than or equal to the supplied argument
19799 * @param {String/Number} target The version to compare with
19800 * @return {Boolean} `true` if this version if greater than or equal to the target, `false` otherwise
19801 */\r
19802 isGreaterThanOrEqual: function(target) {\r
19803 return this.compareTo(target) >= 0;\r
19804 },\r
19805 /**
19806 * Returns whether this version if smaller than the supplied argument
19807 * @param {String/Number} target The version to compare with
19808 * @return {Boolean} `true` if this version if smaller than the target, `false` otherwise
19809 */\r
19810 isLessThan: function(target) {\r
19811 return this.compareTo(target) < 0;\r
19812 },\r
19813 /**
19814 * Returns whether this version if less than or equal to the supplied argument
19815 * @param {String/Number} target The version to compare with
19816 * @return {Boolean} `true` if this version if less than or equal to the target, `false` otherwise
19817 */\r
19818 isLessThanOrEqual: function(target) {\r
19819 return this.compareTo(target) <= 0;\r
19820 },\r
19821 /**
19822 * Returns whether this version equals to the supplied argument
19823 * @param {String/Number} target The version to compare with
19824 * @return {Boolean} `true` if this version equals to the target, `false` otherwise
19825 */\r
19826 equals: function(target) {\r
19827 return this.compareTo(target) === 0;\r
19828 },\r
19829 /**
19830 * Returns whether this version matches the supplied argument. Example:
19831 *
19832 * var version = new Ext.Version('1.0.2beta');
19833 * console.log(version.match(1)); // true
19834 * console.log(version.match(1.0)); // true
19835 * console.log(version.match('1.0.2')); // true
19836 * console.log(version.match('1.0.2RC')); // false
19837 *
19838 * @param {String/Number} target The version to compare with
19839 * @return {Boolean} `true` if this version matches the target, `false` otherwise
19840 */\r
19841 match: function(target) {\r
19842 target = String(target);\r
19843 return this.version.substr(0, target.length) === target;\r
19844 },\r
19845 /**
19846 * Returns this format: [major, minor, patch, build, release]. Useful for comparison.
19847 * @return {Number[]}
19848 */\r
19849 toArray: function() {\r
19850 var me = this;\r
19851 return [\r
19852 me.getMajor(),\r
19853 me.getMinor(),\r
19854 me.getPatch(),\r
19855 me.getBuild(),\r
19856 me.getRelease()\r
19857 ];\r
19858 },\r
19859 /**
19860 * Returns shortVersion version without dots and release
19861 * @return {String}
19862 */\r
19863 getShortVersion: function() {\r
19864 return this.shortVersion;\r
19865 },\r
19866 /**
19867 * Convenient alias to {@link Ext.Version#isGreaterThan isGreaterThan}
19868 * @param {String/Number/Ext.Version} target
19869 * @return {Boolean}
19870 */\r
19871 gt: function(target) {\r
19872 return this.compareTo(target) > 0;\r
19873 },\r
19874 /**
19875 * Convenient alias to {@link Ext.Version#isLessThan isLessThan}
19876 * @param {String/Number/Ext.Version} target
19877 * @return {Boolean}
19878 */\r
19879 lt: function(target) {\r
19880 return this.compareTo(target) < 0;\r
19881 },\r
19882 /**
19883 * Convenient alias to {@link Ext.Version#isGreaterThanOrEqual isGreaterThanOrEqual}
19884 * @param {String/Number/Ext.Version} target
19885 * @return {Boolean}
19886 */\r
19887 gtEq: function(target) {\r
19888 return this.compareTo(target) >= 0;\r
19889 },\r
19890 /**
19891 * Convenient alias to {@link Ext.Version#isLessThanOrEqual isLessThanOrEqual}
19892 * @param {String/Number/Ext.Version} target
19893 * @return {Boolean}
19894 */\r
19895 ltEq: function(target) {\r
19896 return this.compareTo(target) <= 0;\r
19897 }\r
19898 };\r
19899 Ext.apply(Version, {\r
19900 aliases: {\r
19901 from: {\r
19902 extjs: 'ext',\r
19903 core: 'core',\r
19904 touch: 'modern'\r
19905 },\r
19906 to: {\r
19907 ext: [\r
19908 'extjs'\r
19909 ],\r
19910 'core': [\r
19911 'core'\r
19912 ],\r
19913 modern: [\r
19914 'touch'\r
19915 ]\r
19916 }\r
19917 },\r
19918 /**
19919 * @private
19920 */\r
19921 releaseValueMap: {\r
19922 dev: -6,\r
19923 alpha: -5,\r
19924 a: -5,\r
19925 beta: -4,\r
19926 b: -4,\r
19927 rc: -3,\r
19928 '#': -2,\r
19929 p: -1,\r
19930 pl: -1\r
19931 },\r
19932 /**
19933 * Converts a version component to a comparable value
19934 *
19935 * @static
19936 * @param {Object} value The value to convert
19937 * @return {Object}
19938 */\r
19939 getComponentValue: function(value) {\r
19940 return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));\r
19941 },\r
19942 /**
19943 * Compare 2 specified versions by ensuring the first parameter is a `Version`
19944 * instance and then calling the `compareTo` method.
19945 *
19946 * @static
19947 * @param {String} current The current version to compare to
19948 * @param {String} target The target version to compare to
19949 * @return {Number} Returns -1 if the current version is smaller than the target version, 1 if greater, and 0 if they're equivalent
19950 */\r
19951 compare: function(current, target) {\r
19952 var ver = current.isVersion ? current : new Version(current);\r
19953 return ver.compareTo(target);\r
19954 },\r
19955 set: function(collection, packageName, version) {\r
19956 var aliases = Version.aliases.to[packageName],\r
19957 ver = version.isVersion ? version : new Version(version),\r
19958 i;\r
19959 collection[packageName] = ver;\r
19960 if (aliases) {\r
19961 for (i = aliases.length; i-- > 0; ) {\r
19962 collection[aliases[i]] = ver;\r
19963 }\r
19964 }\r
19965 return ver;\r
19966 }\r
19967 });\r
19968 /**
19969 * @class Ext
19970 */\r
19971 Ext.apply(Ext, {\r
19972 /**
19973 * @private
19974 */\r
19975 compatVersions: {},\r
19976 /**
19977 * @private
19978 *
19979 * Object containing version information for all packages utilized by your
19980 * application.
19981 *
19982 * For a public getter, please see `Ext.getVersion()`.
19983 */\r
19984 versions: {},\r
19985 /**
19986 * @private
19987 */\r
19988 lastRegisteredVersion: null,\r
19989 /**
19990 * Get the compatibility level (a version number) for the given package name. If
19991 * none has been registered with `Ext.setCompatVersion` then `Ext.getVersion` is
19992 * used to get the current version.
19993 *
19994 * @param {String} packageName The package name, e.g. 'core', 'touch', 'ext'.
19995 * @since 5.0.0
19996 * @private
19997 */\r
19998 getCompatVersion: function(packageName) {\r
19999 var versions = Ext.compatVersions,\r
20000 compat;\r
20001 if (!packageName) {\r
20002 compat = versions.ext || versions.touch || versions.core;\r
20003 } else {\r
20004 compat = versions[Version.aliases.from[packageName] || packageName];\r
20005 }\r
20006 return compat || Ext.getVersion(packageName);\r
20007 },\r
20008 /**
20009 * Set the compatibility level (a version number) for the given package name.
20010 *
20011 * @param {String} packageName The package name, e.g. 'core', 'touch', 'ext'.
20012 * @param {String/Ext.Version} version The version, e.g. '4.2'.
20013 * @since 5.0.0
20014 * @private
20015 */\r
20016 setCompatVersion: function(packageName, version) {\r
20017 Version.set(Ext.compatVersions, packageName, version);\r
20018 },\r
20019 /**
20020 * Set version number for the given package name.
20021 *
20022 * @param {String} packageName The package name, e.g. 'core', 'touch', 'ext'.
20023 * @param {String/Ext.Version} version The version, e.g. '1.2.3alpha', '2.4.0-dev'.
20024 * @return {Ext}
20025 */\r
20026 setVersion: function(packageName, version) {\r
20027 if (packageName in toolkitNames) {\r
20028 Ext.toolkit = packageName;\r
20029 }\r
20030 Ext.lastRegisteredVersion = Version.set(Ext.versions, packageName, version);\r
20031 return this;\r
20032 },\r
20033 /**
20034 * Get the version number of the supplied package name; will return the version of
20035 * the framework.
20036 *
20037 * @param {String} [packageName] The package name, e.g., 'core', 'touch', 'ext'.
20038 * @return {Ext.Version} The version.
20039 */\r
20040 getVersion: function(packageName) {\r
20041 var versions = Ext.versions;\r
20042 if (!packageName) {\r
20043 return versions.ext || versions.touch || versions.core;\r
20044 }\r
20045 return versions[Version.aliases.from[packageName] || packageName];\r
20046 },\r
20047 /**
20048 * This method checks the registered package versions against the provided version
20049 * `specs`. A `spec` is either a string or an object indicating a boolean operator.
20050 * This method accepts either form or an array of these as the first argument. The
20051 * second argument applies only when the first is an array and indicates whether
20052 * all `specs` must match or just one.
20053 *
20054 * ## Package Version Specifications
20055 * The string form of a `spec` is used to indicate a version or range of versions
20056 * for a particular package. This form of `spec` consists of three (3) parts:
20057 *
20058 * * Package name followed by "@". If not provided, the framework is assumed.
20059 * * Minimum version.
20060 * * Maximum version.
20061 *
20062 * At least one version number must be provided. If both minimum and maximum are
20063 * provided, these must be separated by a "-".
20064 *
20065 * Some examples of package version specifications:
20066 *
20067 * 4.2.2 (exactly version 4.2.2 of the framework)
20068 * 4.2.2+ (version 4.2.2 or higher of the framework)
20069 * 4.2.2- (version 4.2.2 or higher of the framework)
20070 * 4.2.1 - 4.2.3 (versions from 4.2.1 up to 4.2.3 of the framework)
20071 * - 4.2.2 (any version up to version 4.2.1 of the framework)
20072 *
20073 * foo@1.0 (exactly version 1.0 of package "foo")
20074 * foo@1.0-1.3 (versions 1.0 up to 1.3 of package "foo")
20075 *
20076 * **NOTE:** This syntax is the same as that used in Sencha Cmd's package
20077 * requirements declarations.
20078 *
20079 * ## Boolean Operator Specifications
20080 * Instead of a string, an object can be used to describe a boolean operation to
20081 * perform on one or more `specs`. The operator is either **`and`** or **`or`**
20082 * and can contain an optional **`not`**.
20083 *
20084 * For example:
20085 *
20086 * {
20087 * not: true, // negates boolean result
20088 * and: [
20089 * '4.2.2',
20090 * 'foo@1.0.1 - 2.0.1'
20091 * ]
20092 * }
20093 *
20094 * Each element of the array can in turn be a string or object spec. In other
20095 * words, the value is passed to this method (recursively) as the first argument
20096 * so these two calls are equivalent:
20097 *
20098 * Ext.checkVersion({
20099 * not: true, // negates boolean result
20100 * and: [
20101 * '4.2.2',
20102 * 'foo@1.0.1 - 2.0.1'
20103 * ]
20104 * });
20105 *
20106 * !Ext.checkVersion([
20107 * '4.2.2',
20108 * 'foo@1.0.1 - 2.0.1'
20109 * ], true);
20110 *
20111 * ## Examples
20112 *
20113 * // A specific framework version
20114 * Ext.checkVersion('4.2.2');
20115 *
20116 * // A range of framework versions:
20117 * Ext.checkVersion('4.2.1-4.2.3');
20118 *
20119 * // A specific version of a package:
20120 * Ext.checkVersion('foo@1.0.1');
20121 *
20122 * // A single spec that requires both a framework version and package
20123 * // version range to match:
20124 * Ext.checkVersion({
20125 * and: [
20126 * '4.2.2',
20127 * 'foo@1.0.1-1.0.2'
20128 * ]
20129 * });
20130 *
20131 * // These checks can be nested:
20132 * Ext.checkVersion({
20133 * and: [
20134 * '4.2.2', // exactly version 4.2.2 of the framework *AND*
20135 * {
20136 * // either (or both) of these package specs:
20137 * or: [
20138 * 'foo@1.0.1-1.0.2',
20139 * 'bar@3.0+'
20140 * ]
20141 * }
20142 * ]
20143 * });
20144 *
20145 * ## Version Comparisons
20146 * Version comparsions are assumed to be "prefix" based. That is to say, `"foo@1.2"`
20147 * matches any version of "foo" that has a major version 1 and a minor version of 2.
20148 *
20149 * This also applies to ranges. For example `"foo@1.2-2.2"` matches all versions
20150 * of "foo" from 1.2 up to 2.2 regardless of the specific patch and build.
20151 *
20152 * ## Use in Overrides
20153 * This methods primary use is in support of conditional overrides on an
20154 * `Ext.define` declaration.
20155 *
20156 * @param {String/Array/Object} specs A version specification string, an object
20157 * containing `or` or `and` with a value that is equivalent to `specs` or an array
20158 * of either of these.
20159 * @param {Boolean} [matchAll=false] Pass `true` to require all specs to match.
20160 * @return {Boolean} True if `specs` matches the registered package versions.
20161 */\r
20162 checkVersion: function(specs, matchAll) {\r
20163 var isArray = Ext.isArray(specs),\r
20164 aliases = Version.aliases.from,\r
20165 compat = isArray ? specs : checkVerTemp,\r
20166 length = compat.length,\r
20167 versions = Ext.versions,\r
20168 frameworkVer = versions.ext || versions.touch,\r
20169 i, index, matches, minVer, maxVer, packageName, spec, range, ver;\r
20170 if (!isArray) {\r
20171 checkVerTemp[0] = specs;\r
20172 }\r
20173 for (i = 0; i < length; ++i) {\r
20174 if (!Ext.isString(spec = compat[i])) {\r
20175 matches = Ext.checkVersion(spec.and || spec.or, !spec.or);\r
20176 if (spec.not) {\r
20177 matches = !matches;\r
20178 }\r
20179 } else {\r
20180 if (spec.indexOf(' ') >= 0) {\r
20181 spec = spec.replace(stripRe, '');\r
20182 }\r
20183 // For "name@..." syntax, we need to find the package by the given name\r
20184 // as a registered package.\r
20185 index = spec.indexOf('@');\r
20186 if (index < 0) {\r
20187 range = spec;\r
20188 ver = frameworkVer;\r
20189 } else {\r
20190 packageName = spec.substring(0, index);\r
20191 if (!(ver = versions[aliases[packageName] || packageName])) {\r
20192 // The package is not registered, so if we must matchAll then\r
20193 // we are done - FAIL:\r
20194 if (matchAll) {\r
20195 return false;\r
20196 }\r
20197 // Otherwise this spec is not a match so we can move on to the\r
20198 // next...\r
20199 \r
20200 continue;\r
20201 }\r
20202 range = spec.substring(index + 1);\r
20203 }\r
20204 // Now look for a version, version range or partial range:\r
20205 index = range.indexOf('-');\r
20206 if (index < 0) {\r
20207 // just a version or "1.0+"\r
20208 if (range.charAt(index = range.length - 1) === '+') {\r
20209 minVer = range.substring(0, index);\r
20210 maxVer = null;\r
20211 } else {\r
20212 minVer = maxVer = range;\r
20213 }\r
20214 } else if (index > 0) {\r
20215 // a range like "1.0-1.5" or "1.0-"\r
20216 minVer = range.substring(0, index);\r
20217 maxVer = range.substring(index + 1);\r
20218 } else // may be empty\r
20219 {\r
20220 // an upper limit like "-1.5"\r
20221 minVer = null;\r
20222 maxVer = range.substring(index + 1);\r
20223 }\r
20224 matches = true;\r
20225 if (minVer) {\r
20226 minVer = new Version(minVer, '~');\r
20227 // prefix matching\r
20228 matches = minVer.ltEq(ver);\r
20229 }\r
20230 if (matches && maxVer) {\r
20231 maxVer = new Version(maxVer, '~');\r
20232 // prefix matching\r
20233 matches = maxVer.gtEq(ver);\r
20234 }\r
20235 }\r
20236 // string spec\r
20237 if (matches) {\r
20238 // spec matched and we are looking for any match, so we are GO!\r
20239 if (!matchAll) {\r
20240 return true;\r
20241 }\r
20242 } else if (matchAll) {\r
20243 // spec does not match the registered package version\r
20244 return false;\r
20245 }\r
20246 }\r
20247 // In the loop above, for matchAll we return FALSE on mismatch, so getting\r
20248 // here with matchAll means we had no mismatches. On the other hand, if we\r
20249 // are !matchAll, we return TRUE on match and so we get here only if we found\r
20250 // no matches.\r
20251 return !!matchAll;\r
20252 },\r
20253 /**
20254 * Create a closure for deprecated code.
20255 *
20256 * // This means Ext.oldMethod is only supported in 4.0.0beta and older.
20257 * // If Ext.getVersion('extjs') returns a version that is later than '4.0.0beta', for example '4.0.0RC',
20258 * // the closure will not be invoked
20259 * Ext.deprecate('extjs', '4.0.0beta', function() {
20260 * Ext.oldMethod = Ext.newMethod;
20261 *
20262 * ...
20263 * });
20264 *
20265 * @param {String} packageName The package name
20266 * @param {String} since The last version before it's deprecated
20267 * @param {Function} closure The callback function to be executed with the specified version is less than the current version
20268 * @param {Object} scope The execution scope (`this`) if the closure
20269 * @private
20270 */\r
20271 deprecate: function(packageName, since, closure, scope) {\r
20272 if (Version.compare(Ext.getVersion(packageName), since) < 1) {\r
20273 closure.call(scope);\r
20274 }\r
20275 }\r
20276 });\r
20277}());\r
20278// End Versioning\r
20279// load the cmd-5 style app manifest metadata now, if available...\r
20280(function(manifest) {\r
20281 var packages = (manifest && manifest.packages) || {},\r
20282 compat = manifest && manifest.compatibility,\r
20283 name, pkg;\r
20284 for (name in packages) {\r
20285 pkg = packages[name];\r
20286 Ext.setVersion(name, pkg.version);\r
20287 }\r
20288 if (compat) {\r
20289 if (Ext.isString(compat)) {\r
20290 Ext.setCompatVersion('core', compat);\r
20291 } else {\r
20292 for (name in compat) {\r
20293 Ext.setCompatVersion(name, compat[name]);\r
20294 }\r
20295 }\r
20296 }\r
20297 if (!packages.ext && !packages.touch) {\r
20298 Ext.setVersion('ext', '6.0.1.250');\r
20299 Ext.setVersion('core', '6.0.1.250');\r
20300 }\r
20301})(Ext.manifest);\r
20302\r
20303/**
20304 * @class Ext.Config
20305 * This class manages a config property. Instances of this type are created and cached as
20306 * classes declare their config properties. One instance of this class is created per
20307 * config property name.
20308 *
20309 * Ext.define('MyClass', {
20310 * config: {
20311 * foo: 42
20312 * }
20313 * });
20314 *
20315 * This uses the cached `Ext.Config` instance for the "foo" property.
20316 *
20317 * When config properties apply options to config properties a prototype chained object is
20318 * created from the cached instance. For example:
20319 *
20320 * Ext.define('MyClass', {
20321 * config: {
20322 * foo: {
20323 * $value: 42,
20324 * lazy: true
20325 * }
20326 * }
20327 * });
20328 *
20329 * This creates a prototype chain to the cached "foo" instance of `Ext.Config` and applies
20330 * the `lazy` option to that new instance. This chained instance is then kept by the
20331 * `Ext.Configurator` for that class.
20332 * @private
20333 */\r
20334Ext.Config = function(name) {\r
20335 // @define Ext.class.Config\r
20336 // @define Ext.Config\r
20337 var me = this,\r
20338 capitalizedName = name.charAt(0).toUpperCase() + name.substr(1);\r
20339 /**
20340 * @property {String} name
20341 * The name of this config property.
20342 * @readonly
20343 * @private
20344 * @since 5.0.0
20345 */\r
20346 me.name = name;\r
20347 /**
20348 * @property {Object} names
20349 * This object holds the cached names used to lookup properties or methods for this
20350 * config property. The properties of this object are explained in the context of an
20351 * example property named "foo".
20352 *
20353 * @property {String} names.internal The default backing property ("_foo").
20354 *
20355 * @property {String} names.initializing The property that is `true` when the config
20356 * is being initialized ("isFooInitializing").
20357 *
20358 * @property {String} names.apply The name of the applier method ("applyFoo").
20359 *
20360 * @property {String} names.update The name of the updater method ("updateFoo").
20361 *
20362 * @property {String} names.get The name of the getter method ("getFoo").
20363 *
20364 * @property {String} names.set The name of the setter method ("setFoo").
20365 *
20366 * @property {String} names.initGet The name of the initializing getter ("initGetFoo").
20367 *
20368 * @property {String} names.changeEvent The name of the change event ("foochange").
20369 *
20370 * @readonly
20371 * @private
20372 * @since 5.0.0
20373 */\r
20374 me.names = {\r
20375 internal: '_' + name,\r
20376 initializing: 'is' + capitalizedName + 'Initializing',\r
20377 apply: 'apply' + capitalizedName,\r
20378 update: 'update' + capitalizedName,\r
20379 get: 'get' + capitalizedName,\r
20380 set: 'set' + capitalizedName,\r
20381 initGet: 'initGet' + capitalizedName,\r
20382 changeEvent: name.toLowerCase() + 'change'\r
20383 };\r
20384 // This allows folks to prototype chain on top of these objects and yet still cache\r
20385 // generated methods at the bottom of the chain.\r
20386 me.root = me;\r
20387};\r
20388Ext.Config.map = {};\r
20389Ext.Config.get = function(name) {\r
20390 var map = Ext.Config.map,\r
20391 ret = map[name] || (map[name] = new Ext.Config(name));\r
20392 return ret;\r
20393};\r
20394Ext.Config.prototype = {\r
20395 self: Ext.Config,\r
20396 isConfig: true,\r
20397 /**
20398 * @cfg {Boolean} [cached=false]
20399 * When set as `true` the config property will be stored on the class prototype once
20400 * the first instance has had a chance to process the default value.
20401 * @private
20402 * @since 5.0.0
20403 */\r
20404 /**
20405 * @cfg {Boolean} [lazy=false]
20406 * When set as `true` the config property will not be immediately initialized during
20407 * the `initConfig` call.
20408 * @private
20409 * @since 5.0.0
20410 */\r
20411 /**
20412 * @cfg {Boolean} [evented=false]
20413 * When set as `true` the config property will be treated as a {@link Ext.Evented Evented Config}.
20414 * @private
20415 * @since 5.5.0
20416 */\r
20417 /**
20418 * @cfg {Function} [merge]
20419 * This function if supplied will be called as classes or instances provide values
20420 * that need to be combined with inherited values. The function should return the
20421 * value that will be the config value. Further calls may receive such returned
20422 * values as `oldValue`.
20423 *
20424 * @cfg {Mixed} merge.newValue The new value to merge with the old.
20425 *
20426 * @cfg {Mixed} merge.oldValue The current value prior to `newValue` being merged.
20427 *
20428 * @cfg {Mixed} merge.target The class or instance to which the merged config value
20429 * will be applied.
20430 *
20431 * @cfg {Ext.Class} merge.mixinClass The mixin providing the `newValue` or `null` if
20432 * the `newValue` is not being provided by a mixin.
20433 */\r
20434 getGetter: function() {\r
20435 return this.getter || (this.root.getter = this.makeGetter());\r
20436 },\r
20437 getInitGetter: function() {\r
20438 return this.initGetter || (this.root.initGetter = this.makeInitGetter());\r
20439 },\r
20440 getSetter: function() {\r
20441 return this.setter || (this.root.setter = this.makeSetter());\r
20442 },\r
20443 getEventedSetter: function() {\r
20444 return this.eventedSetter || (this.root.eventedSetter = this.makeEventedSetter());\r
20445 },\r
20446 /**
20447 * Returns the name of the property that stores this config on the given instance or
20448 * class prototype.
20449 * @param {Object} target
20450 * @return {String}
20451 */\r
20452 getInternalName: function(target) {\r
20453 return target.$configPrefixed ? this.names.internal : this.name;\r
20454 },\r
20455 mergeNew: function(newValue, oldValue, target, mixinClass) {\r
20456 var ret, key;\r
20457 if (!oldValue) {\r
20458 ret = newValue;\r
20459 } else if (!newValue) {\r
20460 ret = oldValue;\r
20461 } else {\r
20462 ret = Ext.Object.chain(oldValue);\r
20463 for (key in newValue) {\r
20464 if (!mixinClass || !(key in ret)) {\r
20465 ret[key] = newValue[key];\r
20466 }\r
20467 }\r
20468 }\r
20469 return ret;\r
20470 },\r
20471 /**
20472 * Merges the `newValue` and the `oldValue` assuming that these are basically objects
20473 * the represent sets. For example something like:
20474 *
20475 * {
20476 * foo: true,
20477 * bar: true
20478 * }
20479 *
20480 * The merge process converts arrays like the following into the above:
20481 *
20482 * [ 'foo', 'bar' ]
20483 *
20484 * @param {String/String[]/Object} newValue
20485 * @param {Object} oldValue
20486 * @param {Boolean} [preserveExisting=false]
20487 * @return {Object}
20488 * @private
20489 * @since 5.0.0
20490 */\r
20491 mergeSets: function(newValue, oldValue, preserveExisting) {\r
20492 var ret = oldValue ? Ext.Object.chain(oldValue) : {},\r
20493 i, val;\r
20494 if (newValue instanceof Array) {\r
20495 for (i = newValue.length; i--; ) {\r
20496 val = newValue[i];\r
20497 if (!preserveExisting || !(val in ret)) {\r
20498 ret[val] = true;\r
20499 }\r
20500 }\r
20501 } else if (newValue) {\r
20502 if (newValue.constructor === Object) {\r
20503 for (i in newValue) {\r
20504 val = newValue[i];\r
20505 if (!preserveExisting || !(i in ret)) {\r
20506 ret[i] = val;\r
20507 }\r
20508 }\r
20509 } else if (!preserveExisting || !(newValue in ret)) {\r
20510 ret[newValue] = true;\r
20511 }\r
20512 }\r
20513 return ret;\r
20514 },\r
20515 //--------------------------------------------------\r
20516 // Factories\r
20517 makeGetter: function() {\r
20518 var name = this.name,\r
20519 prefixedName = this.names.internal;\r
20520 return function() {\r
20521 var internalName = this.$configPrefixed ? prefixedName : name;\r
20522 return this[internalName];\r
20523 };\r
20524 },\r
20525 makeInitGetter: function() {\r
20526 var name = this.name,\r
20527 names = this.names,\r
20528 setName = names.set,\r
20529 getName = names.get,\r
20530 initializingName = names.initializing;\r
20531 return function() {\r
20532 var me = this;\r
20533 me[initializingName] = true;\r
20534 // Remove the initGetter from the instance now that the value has been set.\r
20535 delete me[getName];\r
20536 me[setName](me.config[name]);\r
20537 delete me[initializingName];\r
20538 return me[getName].apply(me, arguments);\r
20539 };\r
20540 },\r
20541 makeSetter: function() {\r
20542 var name = this.name,\r
20543 names = this.names,\r
20544 prefixedName = names.internal,\r
20545 getName = names.get,\r
20546 applyName = names.apply,\r
20547 updateName = names.update,\r
20548 setter;\r
20549 // http://jsperf.com/method-call-apply-or-direct\r
20550 // http://jsperf.com/method-detect-invoke\r
20551 setter = function(value) {\r
20552 var me = this,\r
20553 internalName = me.$configPrefixed ? prefixedName : name,\r
20554 oldValue = me[internalName];\r
20555 // Remove the initGetter from the instance now that the value has been set.\r
20556 delete me[getName];\r
20557 if (!me[applyName] || (value = me[applyName](value, oldValue)) !== undefined) {\r
20558 // The old value might have been changed at this point\r
20559 // (after the apply call chain) so it should be read again\r
20560 if (value !== (oldValue = me[internalName])) {\r
20561 me[internalName] = value;\r
20562 if (me[updateName]) {\r
20563 me[updateName](value, oldValue);\r
20564 }\r
20565 }\r
20566 }\r
20567 return me;\r
20568 };\r
20569 setter.$isDefault = true;\r
20570 return setter;\r
20571 },\r
20572 makeEventedSetter: function() {\r
20573 var name = this.name,\r
20574 names = this.names,\r
20575 prefixedName = names.internal,\r
20576 getName = names.get,\r
20577 applyName = names.apply,\r
20578 updateName = names.update,\r
20579 changeEventName = names.changeEvent,\r
20580 updateFn = function(me, value, oldValue, internalName) {\r
20581 me[internalName] = value;\r
20582 if (me[updateName]) {\r
20583 me[updateName](value, oldValue);\r
20584 }\r
20585 },\r
20586 setter;\r
20587 // http://jsperf.com/method-call-apply-or-direct\r
20588 // http://jsperf.com/method-detect-invoke\r
20589 setter = function(value) {\r
20590 var me = this,\r
20591 internalName = me.$configPrefixed ? prefixedName : name,\r
20592 oldValue = me[internalName];\r
20593 // Remove the initGetter from the instance now that the value has been set.\r
20594 delete me[getName];\r
20595 if (!me[applyName] || (value = me[applyName](value, oldValue)) !== undefined) {\r
20596 // The old value might have been changed at this point\r
20597 // (after the apply call chain) so it should be read again\r
20598 if (value !== (oldValue = me[internalName])) {\r
20599 if (me.isConfiguring) {\r
20600 me[internalName] = value;\r
20601 if (me[updateName]) {\r
20602 me[updateName](value, oldValue);\r
20603 }\r
20604 } else {\r
20605 me.fireEventedAction(changeEventName, [\r
20606 me,\r
20607 value,\r
20608 oldValue\r
20609 ], updateFn, me, [\r
20610 me,\r
20611 value,\r
20612 oldValue,\r
20613 internalName\r
20614 ]);\r
20615 }\r
20616 }\r
20617 }\r
20618 return me;\r
20619 };\r
20620 setter.$isDefault = true;\r
20621 return setter;\r
20622 }\r
20623};\r
20624\r
20625/**
20626 * @class Ext.Configurator
20627 * This class manages the config properties for a class.
20628 * @private
20629 */\r
20630(function() {\r
20631 // see end of file (and please don't indent the whole file)\r
20632 var ExtConfig = Ext.Config,\r
20633 configPropMap = ExtConfig.map,\r
20634 ExtObject = Ext.Object;\r
20635 Ext.Configurator = function(cls) {\r
20636 // @define Ext.class.Configurator\r
20637 // @define Ext.Configurator\r
20638 // @require Ext.Config\r
20639 var me = this,\r
20640 prototype = cls.prototype,\r
20641 superCfg = cls.superclass ? cls.superclass.self.$config : null;\r
20642 /**
20643 * @property {Ext.Class} cls The class to which this instance is associated.
20644 * @private
20645 * @readonly
20646 */\r
20647 me.cls = cls;\r
20648 /**
20649 * The super class `Configurator` instance or `null` if there is no super class.
20650 *
20651 * @property {Ext.Configurator} superCfg
20652 * @private
20653 * @readonly
20654 */\r
20655 me.superCfg = superCfg;\r
20656 if (superCfg) {\r
20657 /**
20658 * This object holds an `Ext.Config` value for each config property keyed by name.
20659 * This object has as its prototype object the `configs` of its super class.
20660 *
20661 * This map is maintained as each property is added via the `add` method.
20662 *
20663 * @property {Object} configs
20664 * @private
20665 * @readonly
20666 */\r
20667 me.configs = ExtObject.chain(superCfg.configs);\r
20668 /**
20669 * This object holds a bool value for each cachedConfig property keyed by name.
20670 *
20671 * This map is maintained as each property is added via the `add` method.
20672 *
20673 * @property {Object} cachedConfigs
20674 * @private
20675 * @readonly
20676 */\r
20677 me.cachedConfigs = ExtObject.chain(superCfg.cachedConfigs);\r
20678 /**
20679 * This object holds a `Number` for each config property keyed by name. This object has
20680 * as its prototype object the `initMap` of its super class. The value of each property
20681 * has the following meaning:
20682 *
20683 * * `0` - initial value is `null` and requires no processing.
20684 * * `1` - initial value must be set on each instance.
20685 * * `2` - initial value can be cached on the prototype by the first instance.
20686 *
20687 * Any `null` values will either never be added to this map or (if added by a base
20688 * class and set to `null` by a derived class) will cause the entry to be 0.
20689 *
20690 * This map is maintained as each property is added via the `add` method.
20691 *
20692 * @property {Object} initMap
20693 * @private
20694 * @readonly
20695 */\r
20696 me.initMap = ExtObject.chain(superCfg.initMap);\r
20697 /**
20698 * This object holds the default value for each config property keyed by name. This
20699 * object has as its prototype object the `values` of its super class.
20700 *
20701 * This map is maintained as each property is added via the `add` method.
20702 *
20703 * @property {Object} values
20704 * @private
20705 * @readonly
20706 */\r
20707 me.values = ExtObject.chain(superCfg.values);\r
20708 me.needsFork = superCfg.needsFork;\r
20709 // The reason this feature is debug only is that we would have to create this\r
20710 // map for all classes because deprecations could be added to bases after the\r
20711 // derived class had created its Configurator.\r
20712 me.deprecations = ExtObject.chain(superCfg.deprecations);\r
20713 } else {\r
20714 me.configs = {};\r
20715 me.cachedConfigs = {};\r
20716 me.initMap = {};\r
20717 me.values = {};\r
20718 me.deprecations = {};\r
20719 }\r
20720 prototype.config = prototype.defaultConfig = me.values;\r
20721 cls.$config = me;\r
20722 };\r
20723 Ext.Configurator.prototype = {\r
20724 self: Ext.Configurator,\r
20725 needsFork: false,\r
20726 /**
20727 * This array holds the properties that need to be set on new instances.
20728 *
20729 * This array is populated when the first instance is passed to `configure` (basically
20730 * when the first instance is created). The entries in `initMap` are iterated to find
20731 * those configs needing per-instance processing.
20732 *
20733 * @property {Ext.Config[]} initList
20734 * @private
20735 */\r
20736 initList: null,\r
20737 /**
20738 * This method adds new config properties. This is called for classes when they are
20739 * declared, then for any mixins that class may define and finally for any overrides
20740 * defined that target the class.
20741 *
20742 * @param {Object} config The config object containing the new config properties.
20743 * @param {Ext.Class} [mixinClass] The mixin class if the configs are from a mixin.
20744 * @private
20745 */\r
20746 add: function(config, mixinClass) {\r
20747 var me = this,\r
20748 Cls = me.cls,\r
20749 configs = me.configs,\r
20750 cachedConfigs = me.cachedConfigs,\r
20751 initMap = me.initMap,\r
20752 prototype = Cls.prototype,\r
20753 mixinConfigs = mixinClass && mixinClass.$config.configs,\r
20754 values = me.values,\r
20755 isObject, meta, isCached, merge, cfg, currentValue, name, names, s, value;\r
20756 for (name in config) {\r
20757 value = config[name];\r
20758 isObject = value && value.constructor === Object;\r
20759 meta = isObject && '$value' in value ? value : null;\r
20760 if (meta) {\r
20761 isCached = !!meta.cached;\r
20762 value = meta.$value;\r
20763 isObject = value && value.constructor === Object;\r
20764 }\r
20765 merge = meta && meta.merge;\r
20766 cfg = configs[name];\r
20767 if (cfg) {\r
20768 // Only proceed with a mixin if we have a custom merge.\r
20769 if (mixinClass) {\r
20770 merge = cfg.merge;\r
20771 if (!merge) {\r
20772 \r
20773 continue;\r
20774 }\r
20775 // Don't want the mixin meta modifying our own\r
20776 meta = null;\r
20777 } else {\r
20778 merge = merge || cfg.merge;\r
20779 }\r
20780 // This means that we've already declared this as a config in a superclass\r
20781 // Let's not allow us to change it here.\r
20782 if (!mixinClass && isCached && !cachedConfigs[name]) {\r
20783 Ext.raise('Redefining config as cached: ' + name + ' in class: ' + Cls.$className);\r
20784 }\r
20785 // There is already a value for this config and we are not allowed to\r
20786 // modify it. So, if it is an object and the new value is also an object,\r
20787 // the result is a merge so we have to merge both on to a new object.\r
20788 currentValue = values[name];\r
20789 if (merge) {\r
20790 value = merge.call(cfg, value, currentValue, Cls, mixinClass);\r
20791 } else if (isObject) {\r
20792 if (currentValue && currentValue.constructor === Object) {\r
20793 // We favor moving the cost of an "extra" copy here because this\r
20794 // is likely to be a rare thing two object values for the same\r
20795 // property. The alternative would be to clone the initial value\r
20796 // to make it safely modifiable even though it is likely to never\r
20797 // need to be modified.\r
20798 value = ExtObject.merge({}, currentValue, value);\r
20799 }\r
20800 }\r
20801 } else // else "currentValue" is a primitive so "value" can just replace it\r
20802 // else "value" is a primitive and it can just replace currentValue\r
20803 {\r
20804 // This is a new property value, so add it to the various maps "as is".\r
20805 // In the majority of cases this value will not be overridden or need to\r
20806 // be forked.\r
20807 if (mixinConfigs) {\r
20808 // Since this is a config from a mixin, we don't want to apply its\r
20809 // meta-ness because it already has. Instead we want to use its cfg\r
20810 // instance:\r
20811 cfg = mixinConfigs[name];\r
20812 meta = null;\r
20813 } else {\r
20814 cfg = ExtConfig.get(name);\r
20815 }\r
20816 configs[name] = cfg;\r
20817 if (cfg.cached || isCached) {\r
20818 cachedConfigs[name] = true;\r
20819 }\r
20820 // Ensure that the new config has a getter and setter. Because this method\r
20821 // is called during class creation as the "config" (or "cachedConfig") is\r
20822 // being processed, the user's methods will not be on the prototype yet.\r
20823 // \r
20824 // This has the following trade-offs:\r
20825 // \r
20826 // - Custom getters are rare so there is minimal waste generated by them.\r
20827 // \r
20828 // - Custom setters are more common but, by putting the default setter on\r
20829 // the prototype prior to addMembers, when the user methods are added\r
20830 // callParent can be used to call the generated setter. This is almost\r
20831 // certainly desirable as the setter has some very important semantics\r
20832 // that a custom setter would probably want to preserve by just adding\r
20833 // logic before and/or after the callParent.\r
20834 // \r
20835 // - By not adding these to the class body we avoid all the "is function"\r
20836 // tests that get applied to each class member thereby streamlining the\r
20837 // downstream class creation process.\r
20838 //\r
20839 // We still check for getter and/or setter but primarily for reasons of\r
20840 // backwards compatibility and "just in case" someone relied on inherited\r
20841 // getter/setter even though the base did not have the property listed as\r
20842 // a "config" (obscure case certainly).\r
20843 //\r
20844 names = cfg.names;\r
20845 if (!prototype[s = names.get]) {\r
20846 prototype[s] = cfg.getter || cfg.getGetter();\r
20847 }\r
20848 if (!prototype[s = names.set]) {\r
20849 prototype[s] = (meta && meta.evented) ? (cfg.eventedSetter || cfg.getEventedSetter()) : (cfg.setter || cfg.getSetter());\r
20850 }\r
20851 }\r
20852 if (meta) {\r
20853 if (cfg.owner !== Cls) {\r
20854 configs[name] = cfg = Ext.Object.chain(cfg);\r
20855 cfg.owner = Cls;\r
20856 }\r
20857 Ext.apply(cfg, meta);\r
20858 delete cfg.$value;\r
20859 }\r
20860 // Fork checks all the default values to see if they are arrays or objects\r
20861 // Do this to save us from doing it on each run\r
20862 if (!me.needsFork && value && (value.constructor === Object || value instanceof Array)) {\r
20863 me.needsFork = true;\r
20864 }\r
20865 // If the value is non-null, we need to initialize it.\r
20866 if (value !== null) {\r
20867 initMap[name] = true;\r
20868 } else {\r
20869 if (prototype.$configPrefixed) {\r
20870 prototype[configs[name].names.internal] = null;\r
20871 } else {\r
20872 prototype[configs[name].name] = null;\r
20873 }\r
20874 if (name in initMap) {\r
20875 // Only set this to false if we already have it in the map, otherwise, just leave it out!\r
20876 initMap[name] = false;\r
20877 }\r
20878 }\r
20879 values[name] = value;\r
20880 }\r
20881 },\r
20882 addDeprecations: function(configs) {\r
20883 var me = this,\r
20884 deprecations = me.deprecations,\r
20885 className = (me.cls.$className || '') + '#',\r
20886 message, newName, oldName;\r
20887 for (oldName in configs) {\r
20888 newName = configs[oldName];\r
20889 // configs: {\r
20890 // dead: null,\r
20891 //\r
20892 // renamed: 'newName',\r
20893 //\r
20894 // removed: {\r
20895 // message: 'This config was replaced by pixie dust'\r
20896 // }\r
20897 // }\r
20898 if (!newName) {\r
20899 message = 'This config has been removed.';\r
20900 } else if (!(message = newName.message)) {\r
20901 message = 'This config has been renamed to "' + newName + '"';\r
20902 }\r
20903 deprecations[oldName] = className + oldName + ': ' + message;\r
20904 }\r
20905 },\r
20906 /**
20907 * This method configures the given `instance` using the specified `instanceConfig`.
20908 * The given `instance` should have been created by this object's `cls`.
20909 *
20910 * @param {Object} instance The instance to configure.
20911 * @param {Object} instanceConfig The configuration properties to apply to `instance`.
20912 * @private
20913 */\r
20914 configure: function(instance, instanceConfig) {\r
20915 var me = this,\r
20916 configs = me.configs,\r
20917 deprecations = me.deprecations,\r
20918 initMap = me.initMap,\r
20919 initListMap = me.initListMap,\r
20920 initList = me.initList,\r
20921 prototype = me.cls.prototype,\r
20922 values = me.values,\r
20923 remaining = 0,\r
20924 firstInstance = !initList,\r
20925 cachedInitList, cfg, getter, needsInit, i, internalName, ln, names, name, value, isCached, valuesKey, field;\r
20926 values = me.needsFork ? ExtObject.fork(values) : ExtObject.chain(values);\r
20927 // Let apply/update methods know that the initConfig is currently running.\r
20928 instance.isConfiguring = true;\r
20929 if (firstInstance) {\r
20930 // When called to configure the first instance of the class to which we are\r
20931 // bound we take a bit to plan for instance 2+.\r
20932 me.initList = initList = [];\r
20933 me.initListMap = initListMap = {};\r
20934 instance.isFirstInstance = true;\r
20935 for (name in initMap) {\r
20936 needsInit = initMap[name];\r
20937 cfg = configs[name];\r
20938 isCached = cfg.cached;\r
20939 if (needsInit) {\r
20940 names = cfg.names;\r
20941 value = values[name];\r
20942 if (!prototype[names.set].$isDefault || prototype[names.apply] || prototype[names.update] || typeof value === 'object') {\r
20943 if (isCached) {\r
20944 // This is a cachedConfig, so it needs to be initialized with\r
20945 // the default value and placed on the prototype... but the\r
20946 // instanceConfig may have a different value so the value may\r
20947 // need resetting. We have to defer the call to the setter so\r
20948 // that all of the initGetters are set up first.\r
20949 (cachedInitList || (cachedInitList = [])).push(cfg);\r
20950 } else {\r
20951 // Remember this config so that all instances (including this\r
20952 // one) can invoke the setter to properly initialize it.\r
20953 initList.push(cfg);\r
20954 initListMap[name] = true;\r
20955 }\r
20956 // Point all getters to the initGetters. By doing this here we\r
20957 // avoid creating initGetters for configs that don't need them\r
20958 // and we can easily pick up the cached fn to save the call.\r
20959 instance[names.get] = cfg.initGetter || cfg.getInitGetter();\r
20960 } else {\r
20961 // Non-object configs w/o custom setter, applier or updater can\r
20962 // be simply stored on the prototype.\r
20963 prototype[cfg.getInternalName(prototype)] = value;\r
20964 }\r
20965 } else if (isCached) {\r
20966 prototype[cfg.getInternalName(prototype)] = undefined;\r
20967 }\r
20968 }\r
20969 }\r
20970 // TODO - we need to combine the cached loop with the instanceConfig loop to\r
20971 // avoid duplication of init getter setups (for correctness if a cached cfg\r
20972 // calls on a non-cached cfg)\r
20973 ln = cachedInitList && cachedInitList.length;\r
20974 if (ln) {\r
20975 // This is only ever done on the first instance we configure. Any config in\r
20976 // cachedInitList has to be set to the default value to allow any side-effects\r
20977 // or transformations to occur. The resulting values can then be elevated to\r
20978 // the prototype and this property need not be initialized on each instance.\r
20979 for (i = 0; i < ln; ++i) {\r
20980 internalName = cachedInitList[i].getInternalName(prototype);\r
20981 // Since these are cached configs the base class will potentially have put\r
20982 // its cached values on the prototype so we need to hide these while we\r
20983 // run the inits for our cached configs.\r
20984 instance[internalName] = null;\r
20985 }\r
20986 for (i = 0; i < ln; ++i) {\r
20987 names = (cfg = cachedInitList[i]).names;\r
20988 getter = names.get;\r
20989 if (instance.hasOwnProperty(getter)) {\r
20990 instance[names.set](values[cfg.name]);\r
20991 delete instance[getter];\r
20992 }\r
20993 }\r
20994 for (i = 0; i < ln; ++i) {\r
20995 internalName = cachedInitList[i].getInternalName(prototype);\r
20996 prototype[internalName] = instance[internalName];\r
20997 delete instance[internalName];\r
20998 }\r
20999 }\r
21000 // The cachedConfigs have all been set to the default values including any of\r
21001 // those that may have been triggered by their getter.\r
21002 // If the instanceConfig has a platformConfig in it, we need to merge the active\r
21003 // rules of that object to make the actual instanceConfig.\r
21004 if (instanceConfig && instanceConfig.platformConfig) {\r
21005 instanceConfig = me.resolvePlatformConfig(instance, instanceConfig);\r
21006 }\r
21007 if (firstInstance) {\r
21008 // Allow the class to do things once the cachedConfig has been processed.\r
21009 // We need to call this method always when the first instance is configured\r
21010 // whether or not it actually has cached configs\r
21011 if (instance.afterCachedConfig && !instance.afterCachedConfig.$nullFn) {\r
21012 instance.afterCachedConfig(instanceConfig);\r
21013 }\r
21014 }\r
21015 // Now that the cachedConfigs have been processed we can apply the instanceConfig\r
21016 // and hide the "configs" on the prototype. This will serve as the source for any\r
21017 // configs that need to initialize from their initial getter call.\r
21018 instance.config = values;\r
21019 // There are 2 possibilities here:\r
21020 // 1) If it's the first time in this function, we may have had cachedConfigs running.\r
21021 // these configs may have called the getters for any of the normal getters, which\r
21022 // means the initial getters have been clobbered on the instance and won't be able\r
21023 // to be called below when we iterate over the initList. As such, we need to\r
21024 // reinitialize them here, even though we've done it up above.\r
21025 //\r
21026 // 2) If this the second time in this function, the cachedConfigs won't be processed,\r
21027 // so we don't need to worry about them clobbering config values. However, since\r
21028 // we've already done all our setup, we won't enter into the block that sets the\r
21029 // initGetter, so we need to do it here anyway.\r
21030 //\r
21031 // Also note, that lazy configs will appear in the initList because we need\r
21032 // to spin up the initGetter.\r
21033 for (i = 0 , ln = initList.length; i < ln; ++i) {\r
21034 cfg = initList[i];\r
21035 instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();\r
21036 }\r
21037 // Give the class a chance to transform the configs.\r
21038 if (instance.transformInstanceConfig) {\r
21039 instanceConfig = instance.transformInstanceConfig(instanceConfig);\r
21040 }\r
21041 // Important: We are looping here twice on purpose. This first loop serves 2 purposes:\r
21042 //\r
21043 // 1) Ensure the values collection is fully populated before we call any setters. Since\r
21044 // a setter may have an updater/applier, it could potentially call another getter() to grab\r
21045 // the value for some other property, so this ensures they are all set on the config object.\r
21046 //\r
21047 // 2) Ensure that the initGetter is set as the getter for any config that doesn't appear in\r
21048 // the initList. We need to ensure that the initGetter is pushed on for everything that we will\r
21049 // be setting during init time.\r
21050 //\r
21051 // The merging in this loop cannot be completed by Ext.merge(), since we do NOT want to merge\r
21052 // non-strict values, they should always just be assigned across without modification.\r
21053 if (instanceConfig) {\r
21054 for (name in instanceConfig) {\r
21055 value = instanceConfig[name];\r
21056 cfg = configs[name];\r
21057 if (deprecations[name]) {\r
21058 Ext.log.warn(deprecations[name]);\r
21059 if (!cfg) {\r
21060 // If there is a Config for this, perhaps the class is emulating\r
21061 // the old config... If there is not a Config we don't want to\r
21062 // proceed and put the property on the instance. That will likely\r
21063 // hide the bug during development.\r
21064 \r
21065 continue;\r
21066 }\r
21067 }\r
21068 if (!cfg) {\r
21069 field = instance.self.prototype[name];\r
21070 if (instance.$configStrict && (typeof field === 'function') && !field.$nullFn) {\r
21071 // In strict mode you cannot override functions\r
21072 Ext.raise('Cannot override method ' + name + ' on ' + instance.$className + ' instance.');\r
21073 }\r
21074 // Not all "configs" use the config system so in this case simply put\r
21075 // the value on the instance:\r
21076 instance[name] = value;\r
21077 } else {\r
21078 // However we still need to create the initial value that needs\r
21079 // to be used. We also need to spin up the initGetter.\r
21080 if (!cfg.lazy) {\r
21081 ++remaining;\r
21082 }\r
21083 if (!initListMap[name]) {\r
21084 instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();\r
21085 }\r
21086 if (cfg.merge) {\r
21087 value = cfg.merge(value, values[name], instance);\r
21088 } else if (value && value.constructor === Object) {\r
21089 valuesKey = values[name];\r
21090 if (valuesKey && valuesKey.constructor === Object) {\r
21091 value = ExtObject.merge(values[name], value);\r
21092 } else {\r
21093 value = Ext.clone(value);\r
21094 }\r
21095 }\r
21096 }\r
21097 values[name] = value;\r
21098 }\r
21099 }\r
21100 // Give the class a chance to hook in prior to initializing the configs.\r
21101 if (instance.beforeInitConfig && !instance.beforeInitConfig.$nullFn) {\r
21102 if (instance.beforeInitConfig(instanceConfig) === false) {\r
21103 return;\r
21104 }\r
21105 }\r
21106 if (instanceConfig) {\r
21107 for (name in instanceConfig) {\r
21108 if (!remaining) {\r
21109 // For classes that have few proper Config properties, this saves us\r
21110 // from making the full 2 passes over the instanceConfig.\r
21111 break;\r
21112 }\r
21113 // We can ignore deprecated configs here because we warned about them\r
21114 // above. Further, since we only process proper Config's here we would\r
21115 // not be skipping them anyway.\r
21116 cfg = configs[name];\r
21117 if (cfg && !cfg.lazy) {\r
21118 --remaining;\r
21119 // A proper "config" property so call the setter to set the value.\r
21120 names = cfg.names;\r
21121 getter = names.get;\r
21122 // At this point the initGetter may have already been called and\r
21123 // cleared if the getter was called from the applier or updater of a\r
21124 // previously processed instance config. checking if the instance has\r
21125 // its own getter ensures the setter does not get called twice.\r
21126 if (instance.hasOwnProperty(getter)) {\r
21127 instance[names.set](values[name]);\r
21128 // The generated setter will remove the initGetter from the instance\r
21129 // but the user may have provided their own setter so we have to do\r
21130 // this here as well:\r
21131 delete instance[names.get];\r
21132 }\r
21133 }\r
21134 }\r
21135 }\r
21136 // Process configs declared on the class that need per-instance initialization.\r
21137 for (i = 0 , ln = initList.length; i < ln; ++i) {\r
21138 cfg = initList[i];\r
21139 names = cfg.names;\r
21140 getter = names.get;\r
21141 if (!cfg.lazy && instance.hasOwnProperty(getter)) {\r
21142 // Since the instance still hasOwn the getter, that means we've set an initGetter\r
21143 // and it hasn't been cleared by calling any setter. Since we've never set the value\r
21144 // because it wasn't passed in the instance, we go and set it here, taking the value\r
21145 // from our definition config and passing it through finally clear off the getter.\r
21146 instance[names.set](values[cfg.name]);\r
21147 delete instance[getter];\r
21148 }\r
21149 }\r
21150 // Expose the value from the prototype chain (false):\r
21151 delete instance.isConfiguring;\r
21152 },\r
21153 getCurrentConfig: function(instance) {\r
21154 var defaultConfig = instance.defaultConfig,\r
21155 config = {},\r
21156 name;\r
21157 for (name in defaultConfig) {\r
21158 config[name] = instance[configPropMap[name].names.get]();\r
21159 }\r
21160 return config;\r
21161 },\r
21162 /**
21163 * Merges the values of a config object onto a base config.
21164 * @param {Ext.Base} instance
21165 * @param {Object} baseConfig
21166 * @param {Object} config
21167 * @return {Object} the merged config
21168 * @private
21169 */\r
21170 merge: function(instance, baseConfig, config) {\r
21171 // Although this is a "private" method. It is used by Sencha Architect and so\r
21172 // its api should remain stable.\r
21173 var configs = this.configs,\r
21174 name, value, baseValue, cfg;\r
21175 for (name in config) {\r
21176 value = config[name];\r
21177 cfg = configs[name];\r
21178 if (cfg) {\r
21179 if (cfg.merge) {\r
21180 value = cfg.merge(value, baseConfig[name], instance);\r
21181 } else if (value && value.constructor === Object) {\r
21182 baseValue = baseConfig[name];\r
21183 if (baseValue && baseValue.constructor === Object) {\r
21184 value = Ext.Object.merge(baseValue, value);\r
21185 } else {\r
21186 value = Ext.clone(value);\r
21187 }\r
21188 }\r
21189 }\r
21190 baseConfig[name] = value;\r
21191 }\r
21192 return baseConfig;\r
21193 },\r
21194 /**
21195 * @private
21196 */\r
21197 reconfigure: function(instance, instanceConfig, options) {\r
21198 var currentConfig = instance.config,\r
21199 configList = [],\r
21200 strict = instance.$configStrict && !(options && options.strict === false),\r
21201 configs = this.configs,\r
21202 defaults = options && options.defaults,\r
21203 cfg, getter, i, len, name, names, prop;\r
21204 for (name in instanceConfig) {\r
21205 if (defaults && instance.hasOwnProperty(name)) {\r
21206 \r
21207 continue;\r
21208 }\r
21209 currentConfig[name] = instanceConfig[name];\r
21210 cfg = configs[name];\r
21211 if (this.deprecations[name]) {\r
21212 // See similar logic doc in configure() method.\r
21213 Ext.log.warn(this.deprecations[name]);\r
21214 if (!cfg) {\r
21215 \r
21216 continue;\r
21217 }\r
21218 }\r
21219 if (cfg) {\r
21220 // To ensure that configs being set here get processed in the proper order\r
21221 // we must give them init getters just in case they depend upon each other\r
21222 instance[cfg.names.get] = cfg.initGetter || cfg.getInitGetter();\r
21223 } else {\r
21224 // Check for existence of the property on the prototype before proceeding.\r
21225 // If present on the prototype, and if the property is a function we\r
21226 // do not allow it to be overridden by a property in the config object\r
21227 // in strict mode (unless the function on the prototype is a emptyFn or\r
21228 // identityFn). Note that we always check the prototype, not the instance\r
21229 // because calling setConfig a second time should have the same results -\r
21230 // the first call may have set a function on the instance.\r
21231 prop = instance.self.prototype[name];\r
21232 if (strict) {\r
21233 if ((typeof prop === 'function') && !prop.$nullFn) {\r
21234 Ext.Error.raise("Cannot override method " + name + " on " + instance.$className + " instance.");\r
21235 \r
21236 continue;\r
21237 } else {\r
21238 if (name !== 'type') {\r
21239 Ext.log.warn('No such config "' + name + '" for class ' + instance.$className);\r
21240 }\r
21241 }\r
21242 }\r
21243 }\r
21244 configList.push(name);\r
21245 }\r
21246 for (i = 0 , len = configList.length; i < len; i++) {\r
21247 name = configList[i];\r
21248 cfg = configs[name];\r
21249 if (cfg) {\r
21250 names = cfg.names;\r
21251 getter = names.get;\r
21252 if (instance.hasOwnProperty(getter)) {\r
21253 // Since the instance still hasOwn the getter, that means we've set an initGetter\r
21254 // and it hasn't been cleared by calling any setter. Since we've never set the value\r
21255 // because it wasn't passed in the instance, we go and set it here, taking the value\r
21256 // from our definition config and passing it through finally clear off the getter.\r
21257 instance[names.set](instanceConfig[name]);\r
21258 delete instance[getter];\r
21259 }\r
21260 } else {\r
21261 cfg = configPropMap[name] || Ext.Config.get(name);\r
21262 names = cfg.names;\r
21263 if (instance[names.set]) {\r
21264 instance[names.set](instanceConfig[name]);\r
21265 } else {\r
21266 // apply non-config props directly to the instance\r
21267 instance[name] = instanceConfig[name];\r
21268 }\r
21269 }\r
21270 }\r
21271 },\r
21272 /**
21273 * This method accepts an instance config object containing a `platformConfig`
21274 * property and merges the appropriate rules from that sub-object with the root object
21275 * to create the final config object that should be used. This is method called by
21276 * `{@link #configure}` when it receives an `instanceConfig` containing a
21277 * `platformConfig` property.
21278 *
21279 * @param {Object} instanceConfig The instance config parameter.
21280 * @return {Object} The new instance config object with platformConfig results applied.
21281 * @private
21282 * @since 5.1.0
21283 */\r
21284 resolvePlatformConfig: function(instance, instanceConfig) {\r
21285 var platformConfig = instanceConfig && instanceConfig.platformConfig,\r
21286 ret = instanceConfig,\r
21287 i, keys, n;\r
21288 if (platformConfig) {\r
21289 keys = Ext.getPlatformConfigKeys(platformConfig);\r
21290 n = keys.length;\r
21291 if (n) {\r
21292 ret = Ext.merge({}, ret);\r
21293 // this deep copies sub-objects\r
21294 for (i = 0 , n = keys.length; i < n; ++i) {\r
21295 this.merge(instance, ret, platformConfig[keys[i]]);\r
21296 }\r
21297 }\r
21298 }\r
21299 return ret;\r
21300 }\r
21301 };\r
21302}());\r
21303// prototype\r
21304// closure on whole file\r
21305\r
21306// @tag class\r
21307/**
21308 * @class Ext.Base
21309 *
21310 * The root of all classes created with {@link Ext#define}.
21311 *
21312 * Ext.Base is the building block of all Ext classes. All classes in Ext inherit from Ext.Base.
21313 * All prototype and static members of this class are inherited by all other classes.
21314 */\r
21315Ext.Base = (function(flexSetter) {\r
21316 // @define Ext.Base\r
21317 // @require Ext.Util\r
21318 // @require Ext.Version\r
21319 // @require Ext.Configurator\r
21320 // @uses Ext.ClassManager\r
21321 var noArgs = [],\r
21322 baseStaticMember,\r
21323 baseStaticMembers = [],\r
21324 getConfig = function(name, peek) {\r
21325 var me = this,\r
21326 ret, cfg, getterName;\r
21327 if (name) {\r
21328 cfg = Ext.Config.map[name];\r
21329 if (!cfg) {\r
21330 Ext.Logger.error("Invalid property name for getter: '" + name + "' for '" + me.$className + "'.");\r
21331 }\r
21332 getterName = cfg.names.get;\r
21333 if (peek && me.hasOwnProperty(getterName)) {\r
21334 ret = me.config[name];\r
21335 } else {\r
21336 ret = me[getterName]();\r
21337 }\r
21338 } else {\r
21339 ret = me.getCurrentConfig();\r
21340 }\r
21341 return ret;\r
21342 },\r
21343 makeDeprecatedMethod = function(oldName, newName, msg) {\r
21344 var message = '"' + oldName + '" is deprecated.';\r
21345 if (msg) {\r
21346 message += ' ' + msg;\r
21347 } else if (newName) {\r
21348 message += ' Please use "' + newName + '" instead.';\r
21349 }\r
21350 return function() {\r
21351 Ext.raise(message);\r
21352 };\r
21353 },\r
21354 addDeprecatedProperty = function(object, oldName, newName, message) {\r
21355 if (!message) {\r
21356 message = '"' + oldName + '" is deprecated.';\r
21357 }\r
21358 if (newName) {\r
21359 message += ' Please use "' + newName + '" instead.';\r
21360 }\r
21361 if (message) {\r
21362 Ext.Object.defineProperty(object, oldName, {\r
21363 get: function() {\r
21364 Ext.raise(message);\r
21365 },\r
21366 set: function(value) {\r
21367 Ext.raise(message);\r
21368 },\r
21369 configurable: true\r
21370 });\r
21371 }\r
21372 },\r
21373 makeAliasFn = function(name) {\r
21374 return function() {\r
21375 return this[name].apply(this, arguments);\r
21376 };\r
21377 },\r
21378 Version = Ext.Version,\r
21379 leadingDigitRe = /^\d/,\r
21380 oneMember = {},\r
21381 aliasOneMember = {},\r
21382 Base = function() {},\r
21383 BasePrototype = Base.prototype;\r
21384 // These static properties will be copied to every newly created class with {@link Ext#define}\r
21385 Ext.apply(Base, {\r
21386 $className: 'Ext.Base',\r
21387 $isClass: true,\r
21388 /**
21389 * Create a new instance of this Class.
21390 *
21391 * Ext.define('My.cool.Class', {
21392 * ...
21393 * });
21394 *
21395 * My.cool.Class.create({
21396 * someConfig: true
21397 * });
21398 *
21399 * All parameters are passed to the constructor of the class.
21400 *
21401 * @return {Object} the created instance.
21402 * @static
21403 * @inheritable
21404 */\r
21405 create: function() {\r
21406 return Ext.create.apply(Ext, [\r
21407 this\r
21408 ].concat(Array.prototype.slice.call(arguments, 0)));\r
21409 },\r
21410 /**
21411 * This method applies a versioned, deprecation declaration to this class. This
21412 * is typically called by the `deprecated` config.
21413 * @private
21414 */\r
21415 addDeprecations: function(deprecations) {\r
21416 var me = this,\r
21417 all = [],\r
21418 compatVersion = Ext.getCompatVersion(deprecations.name),\r
21419 configurator = me.getConfigurator(),\r
21420 displayName = (me.$className || '') + '#',\r
21421 deprecate, versionSpec, index, message, target, enabled, existing, fn, names, oldName, newName, member, statics, version;\r
21422 for (versionSpec in deprecations) {\r
21423 if (leadingDigitRe.test(versionSpec)) {\r
21424 version = new Ext.Version(versionSpec);\r
21425 version.deprecations = deprecations[versionSpec];\r
21426 all.push(version);\r
21427 }\r
21428 }\r
21429 all.sort(Version.compare);\r
21430 for (index = all.length; index--; ) {\r
21431 deprecate = (version = all[index]).deprecations;\r
21432 target = me.prototype;\r
21433 statics = deprecate.statics;\r
21434 // If user specifies, say 4.2 compatibility and we have a 5.0 deprecation\r
21435 // then that block needs to be "enabled" to "revert" to behaviors prior\r
21436 // to 5.0. By default, compatVersion === currentVersion, so there are no\r
21437 // enabled blocks. In dev mode we still want to visit all the blocks and\r
21438 // possibly add shims to detect use of deprecated methods, but in a build\r
21439 // (if the deprecated block remains somehow) we just break the loop.\r
21440 enabled = compatVersion && compatVersion.lt(version);\r
21441 if (!enabled) {} else if (!enabled) {\r
21442 // we won't get here in dev mode when !enabled\r
21443 break;\r
21444 }\r
21445 while (deprecate) {\r
21446 names = deprecate.methods;\r
21447 if (names) {\r
21448 for (oldName in names) {\r
21449 member = names[oldName];\r
21450 fn = null;\r
21451 if (!member) {\r
21452 /*
21453 * Something like:
21454 *
21455 * '5.1': {
21456 * methods: {
21457 * removedMethod: null
21458 * }
21459 * }
21460 *
21461 * Since there is no recovering the method, we always put
21462 * on a shim to catch abuse.
21463 */\r
21464 // The class should not already have a method by the oldName\r
21465 Ext.Assert.isNotDefinedProp(target, oldName);\r
21466 fn = makeDeprecatedMethod(displayName + oldName);\r
21467 } else if (Ext.isString(member)) {\r
21468 /*
21469 * Something like:
21470 *
21471 * '5.1': {
21472 * methods: {
21473 * oldName: 'newName'
21474 * }
21475 * }
21476 *
21477 * If this block is enabled, we just put an alias in place.
21478 * Otherwise we need to inject a
21479 */\r
21480 // The class should not already have a method by the oldName\r
21481 Ext.Assert.isNotDefinedProp(target, oldName);\r
21482 Ext.Assert.isDefinedProp(target, member);\r
21483 if (enabled) {\r
21484 // This call to the real method name must be late\r
21485 // bound if it is to pick up overrides and such.\r
21486 fn = makeAliasFn(member);\r
21487 } else {\r
21488 fn = makeDeprecatedMethod(displayName + oldName, member);\r
21489 }\r
21490 } else {\r
21491 /*
21492 * Something like:
21493 *
21494 * '5.1': {
21495 * methods: {
21496 * foo: function () { ... }
21497 * }
21498 * }
21499 *
21500 * Or this:
21501 *
21502 * '5.1': {
21503 * methods: {
21504 * foo: {
21505 * fn: function () { ... },
21506 * message: 'Please use "bar" instead.'
21507 * }
21508 * }
21509 * }
21510 *
21511 * Or just this:
21512 *
21513 * '5.1': {
21514 * methods: {
21515 * foo: {
21516 * message: 'Use something else instead.'
21517 * }
21518 * }
21519 * }
21520 *
21521 * If this block is enabled, and "foo" is an existing
21522 * method, than we apply the given method as an override.
21523 * If "foo" is not existing, we simply add the method.
21524 *
21525 * If the block is not enabled and there is no existing
21526 * method by that name, than we add a shim to prevent
21527 * abuse.
21528 */\r
21529 message = '';\r
21530 if (member.message || member.fn) {\r
21531 message = member.message;\r
21532 member = member.fn;\r
21533 }\r
21534 existing = target.hasOwnProperty(oldName) && target[oldName];\r
21535 if (enabled && member) {\r
21536 member.$owner = me;\r
21537 member.$name = oldName;\r
21538 member.name = displayName + oldName;\r
21539 if (existing) {\r
21540 member.$previous = existing;\r
21541 }\r
21542 fn = member;\r
21543 } else if (!existing) {\r
21544 fn = makeDeprecatedMethod(displayName + oldName, null, message);\r
21545 }\r
21546 }\r
21547 if (fn) {\r
21548 target[oldName] = fn;\r
21549 }\r
21550 }\r
21551 }\r
21552 // for oldName\r
21553 //-------------------------------------\r
21554 // Debug only\r
21555 names = deprecate.configs;\r
21556 if (names) {\r
21557 //\r
21558 // '6.0': {\r
21559 // configs: {\r
21560 // dead: null,\r
21561 //\r
21562 // renamed: 'newName',\r
21563 //\r
21564 // removed: {\r
21565 // message: 'This config was replaced by pixie dust'\r
21566 // }\r
21567 // }\r
21568 // }\r
21569 //\r
21570 configurator.addDeprecations(names);\r
21571 }\r
21572 names = deprecate.properties;\r
21573 if (names && !enabled) {\r
21574 // For properties about the only thing we can do is (on Good\r
21575 // Browsers), add warning shims for accessing them. So if the\r
21576 // block is enabled, we don't want those.\r
21577 for (oldName in names) {\r
21578 newName = names[oldName];\r
21579 if (Ext.isString(newName)) {\r
21580 addDeprecatedProperty(target, displayName + oldName, newName);\r
21581 } else if (newName && newName.message) {\r
21582 addDeprecatedProperty(target, displayName + oldName, null, newName.message);\r
21583 } else {\r
21584 addDeprecatedProperty(target, displayName + oldName);\r
21585 }\r
21586 }\r
21587 }\r
21588 //-------------------------------------\r
21589 // reset to handle statics and apply them to the class\r
21590 deprecate = statics;\r
21591 statics = null;\r
21592 target = me;\r
21593 }\r
21594 }\r
21595 },\r
21596 /**
21597 * @private
21598 * @static
21599 * @inheritable
21600 * @param config
21601 */\r
21602 extend: function(parent) {\r
21603 var me = this,\r
21604 parentPrototype = parent.prototype,\r
21605 prototype, i, ln, name, statics;\r
21606 prototype = me.prototype = Ext.Object.chain(parentPrototype);\r
21607 prototype.self = me;\r
21608 me.superclass = prototype.superclass = parentPrototype;\r
21609 if (!parent.$isClass) {\r
21610 for (i in BasePrototype) {\r
21611 if (i in prototype) {\r
21612 prototype[i] = BasePrototype[i];\r
21613 }\r
21614 }\r
21615 }\r
21616 // Statics inheritance\r
21617 statics = parentPrototype.$inheritableStatics;\r
21618 if (statics) {\r
21619 for (i = 0 , ln = statics.length; i < ln; i++) {\r
21620 name = statics[i];\r
21621 if (!me.hasOwnProperty(name)) {\r
21622 me[name] = parent[name];\r
21623 }\r
21624 }\r
21625 }\r
21626 if (parent.$onExtended) {\r
21627 me.$onExtended = parent.$onExtended.slice();\r
21628 }\r
21629 me.getConfigurator();\r
21630 },\r
21631 /**
21632 * @private
21633 * @static
21634 * @inheritable
21635 */\r
21636 $onExtended: [],\r
21637 /**
21638 * @private
21639 * @static
21640 * @inheritable
21641 */\r
21642 triggerExtended: function() {\r
21643 Ext.classSystemMonitor && Ext.classSystemMonitor(this, 'Ext.Base#triggerExtended', arguments);\r
21644 var callbacks = this.$onExtended,\r
21645 ln = callbacks.length,\r
21646 i, callback;\r
21647 if (ln > 0) {\r
21648 for (i = 0; i < ln; i++) {\r
21649 callback = callbacks[i];\r
21650 callback.fn.apply(callback.scope || this, arguments);\r
21651 }\r
21652 }\r
21653 },\r
21654 /**
21655 * @private
21656 * @static
21657 * @inheritable
21658 */\r
21659 onExtended: function(fn, scope) {\r
21660 this.$onExtended.push({\r
21661 fn: fn,\r
21662 scope: scope\r
21663 });\r
21664 return this;\r
21665 },\r
21666 /**
21667 * Add / override static properties of this class.
21668 *
21669 * Ext.define('My.cool.Class', {
21670 * ...
21671 * });
21672 *
21673 * My.cool.Class.addStatics({
21674 * someProperty: 'someValue', // My.cool.Class.someProperty = 'someValue'
21675 * method1: function() { ... }, // My.cool.Class.method1 = function() { ... };
21676 * method2: function() { ... } // My.cool.Class.method2 = function() { ... };
21677 * });
21678 *
21679 * @param {Object} members
21680 * @return {Ext.Base} this
21681 * @static
21682 * @inheritable
21683 */\r
21684 addStatics: function(members) {\r
21685 this.addMembers(members, true);\r
21686 return this;\r
21687 },\r
21688 /**
21689 * @private
21690 * @static
21691 * @inheritable
21692 * @param {Object} members
21693 */\r
21694 addInheritableStatics: function(members) {\r
21695 var inheritableStatics, hasInheritableStatics,\r
21696 prototype = this.prototype,\r
21697 name, member;\r
21698 inheritableStatics = prototype.$inheritableStatics;\r
21699 hasInheritableStatics = prototype.$hasInheritableStatics;\r
21700 if (!inheritableStatics) {\r
21701 inheritableStatics = prototype.$inheritableStatics = [];\r
21702 hasInheritableStatics = prototype.$hasInheritableStatics = {};\r
21703 }\r
21704 var className = Ext.getClassName(this) + '.';\r
21705 for (name in members) {\r
21706 if (members.hasOwnProperty(name)) {\r
21707 member = members[name];\r
21708 if (typeof member == 'function') {\r
21709 member.name = className + name;\r
21710 }\r
21711 this[name] = member;\r
21712 if (!hasInheritableStatics[name]) {\r
21713 hasInheritableStatics[name] = true;\r
21714 inheritableStatics.push(name);\r
21715 }\r
21716 }\r
21717 }\r
21718 return this;\r
21719 },\r
21720 /**
21721 * Add methods / properties to the prototype of this class.
21722 *
21723 * Ext.define('My.awesome.Cat', {
21724 * constructor: function() {
21725 * ...
21726 * }
21727 * });
21728 *
21729 * My.awesome.Cat.addMembers({
21730 * meow: function() {
21731 * alert('Meowww...');
21732 * }
21733 * });
21734 *
21735 * var kitty = new My.awesome.Cat();
21736 * kitty.meow();
21737 *
21738 * @param {Object} members The members to add to this class.
21739 * @param {Boolean} [isStatic=false] Pass `true` if the members are static.
21740 * @param {Boolean} [privacy=false] Pass `true` if the members are private. This
21741 * only has meaning in debug mode and only for methods.
21742 * @static
21743 * @inheritable
21744 */\r
21745 addMembers: function(members, isStatic, privacy) {\r
21746 var me = this,\r
21747 // this class\r
21748 cloneFunction = Ext.Function.clone,\r
21749 target = isStatic ? me : me.prototype,\r
21750 defaultConfig = !isStatic && target.defaultConfig,\r
21751 enumerables = Ext.enumerables,\r
21752 privates = members.privates,\r
21753 configs, i, ln, member, name, subPrivacy, privateStatics;\r
21754 var displayName = (me.$className || '') + '#';\r
21755 if (privates) {\r
21756 // This won't run for normal class private members but will pick up all\r
21757 // others (statics, overrides, etc).\r
21758 delete members.privates;\r
21759 if (!isStatic) {\r
21760 privateStatics = privates.statics;\r
21761 delete privates.statics;\r
21762 }\r
21763 subPrivacy = privates.privacy || privacy || 'framework';\r
21764 me.addMembers(privates, isStatic, subPrivacy);\r
21765 if (privateStatics) {\r
21766 me.addMembers(privateStatics, true, subPrivacy);\r
21767 }\r
21768 }\r
21769 for (name in members) {\r
21770 if (members.hasOwnProperty(name)) {\r
21771 member = members[name];\r
21772 if (privacy === true) {\r
21773 privacy = 'framework';\r
21774 }\r
21775 if (member && member.$nullFn && privacy !== member.$privacy) {\r
21776 Ext.raise('Cannot use stock function for private method ' + (me.$className ? me.$className + '#' : '') + name);\r
21777 }\r
21778 if (typeof member === 'function' && !member.$isClass && !member.$nullFn) {\r
21779 if (member.$owner) {\r
21780 member = cloneFunction(member);\r
21781 }\r
21782 if (target.hasOwnProperty(name)) {\r
21783 member.$previous = target[name];\r
21784 }\r
21785 // This information is needed by callParent() and callSuper() as\r
21786 // well as statics() and even Ext.fly().\r
21787 member.$owner = me;\r
21788 member.$name = name;\r
21789 member.name = displayName + name;\r
21790 var existing = target[name];\r
21791 if (privacy) {\r
21792 member.$privacy = privacy;\r
21793 // The general idea here is that an existing, non-private\r
21794 // method can be marked private. This is because the other\r
21795 // way is strictly forbidden (private method going public)\r
21796 // so if a method is in that gray area it can only be made\r
21797 // private in doc form which allows a derived class to make\r
21798 // it public.\r
21799 if (existing && existing.$privacy && existing.$privacy !== privacy) {\r
21800 Ext.privacyViolation(me, existing, member, isStatic);\r
21801 }\r
21802 } else if (existing && existing.$privacy) {\r
21803 Ext.privacyViolation(me, existing, member, isStatic);\r
21804 }\r
21805 }\r
21806 // The last part of the check here resolves a conflict if we have the same property\r
21807 // declared as both a config and a member on the class so that the config wins.\r
21808 else if (defaultConfig && (name in defaultConfig) && !target.config.hasOwnProperty(name)) {\r
21809 // This is a config property so it must be added to the configs\r
21810 // collection not just smashed on the prototype...\r
21811 (configs || (configs = {}))[name] = member;\r
21812 \r
21813 continue;\r
21814 }\r
21815 target[name] = member;\r
21816 }\r
21817 }\r
21818 if (configs) {\r
21819 // Add any configs found in the normal members arena:\r
21820 me.addConfig(configs);\r
21821 }\r
21822 if (enumerables) {\r
21823 for (i = 0 , ln = enumerables.length; i < ln; ++i) {\r
21824 if (members.hasOwnProperty(name = enumerables[i])) {\r
21825 member = members[name];\r
21826 // The enumerables are all functions...\r
21827 if (member && !member.$nullFn) {\r
21828 if (member.$owner) {\r
21829 member = cloneFunction(member);\r
21830 }\r
21831 member.$owner = me;\r
21832 member.$name = name;\r
21833 member.name = displayName + name;\r
21834 if (target.hasOwnProperty(name)) {\r
21835 member.$previous = target[name];\r
21836 }\r
21837 }\r
21838 target[name] = member;\r
21839 }\r
21840 }\r
21841 }\r
21842 return this;\r
21843 },\r
21844 /**
21845 * @private
21846 * @static
21847 * @inheritable
21848 * @param name
21849 * @param member
21850 */\r
21851 addMember: function(name, member) {\r
21852 oneMember[name] = member;\r
21853 this.addMembers(oneMember);\r
21854 delete oneMember[name];\r
21855 return this;\r
21856 },\r
21857 /**
21858 * Borrow another class' members to the prototype of this class.
21859 *
21860 * Ext.define('Bank', {
21861 * money: '$$$',
21862 * printMoney: function() {
21863 * alert('$$$$$$$');
21864 * }
21865 * });
21866 *
21867 * Ext.define('Thief', {
21868 * ...
21869 * });
21870 *
21871 * Thief.borrow(Bank, ['money', 'printMoney']);
21872 *
21873 * var steve = new Thief();
21874 *
21875 * alert(steve.money); // alerts '$$$'
21876 * steve.printMoney(); // alerts '$$$$$$$'
21877 *
21878 * @param {Ext.Base} fromClass The class to borrow members from
21879 * @param {Array/String} members The names of the members to borrow
21880 * @return {Ext.Base} this
21881 * @static
21882 * @inheritable
21883 * @private
21884 */\r
21885 borrow: function(fromClass, members) {\r
21886 Ext.classSystemMonitor && Ext.classSystemMonitor(this, 'Ext.Base#borrow', arguments);\r
21887 var prototype = fromClass.prototype,\r
21888 membersObj = {},\r
21889 i, ln, name;\r
21890 members = Ext.Array.from(members);\r
21891 for (i = 0 , ln = members.length; i < ln; i++) {\r
21892 name = members[i];\r
21893 membersObj[name] = prototype[name];\r
21894 }\r
21895 return this.addMembers(membersObj);\r
21896 },\r
21897 /**
21898 * Override members of this class. Overridden methods can be invoked via
21899 * {@link Ext.Base#callParent}.
21900 *
21901 * Ext.define('My.Cat', {
21902 * constructor: function() {
21903 * alert("I'm a cat!");
21904 * }
21905 * });
21906 *
21907 * My.Cat.override({
21908 * constructor: function() {
21909 * alert("I'm going to be a cat!");
21910 *
21911 * this.callParent(arguments);
21912 *
21913 * alert("Meeeeoooowwww");
21914 * }
21915 * });
21916 *
21917 * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"
21918 * // alerts "I'm a cat!"
21919 * // alerts "Meeeeoooowwww"
21920 *
21921 * Direct use of this method should be rare. Use {@link Ext#define Ext.define}
21922 * instead:
21923 *
21924 * Ext.define('My.CatOverride', {
21925 * override: 'My.Cat',
21926 * constructor: function() {
21927 * alert("I'm going to be a cat!");
21928 *
21929 * this.callParent(arguments);
21930 *
21931 * alert("Meeeeoooowwww");
21932 * }
21933 * });
21934 *
21935 * The above accomplishes the same result but can be managed by the {@link Ext.Loader}
21936 * which can properly order the override and its target class and the build process
21937 * can determine whether the override is needed based on the required state of the
21938 * target class (My.Cat).
21939 *
21940 * @param {Object} members The properties to add to this class. This should be
21941 * specified as an object literal containing one or more properties.
21942 * @return {Ext.Base} this class
21943 * @static
21944 * @inheritable
21945 */\r
21946 override: function(members) {\r
21947 var me = this,\r
21948 statics = members.statics,\r
21949 inheritableStatics = members.inheritableStatics,\r
21950 config = members.config,\r
21951 mixins = members.mixins,\r
21952 cachedConfig = members.cachedConfig;\r
21953 if (statics || inheritableStatics || config) {\r
21954 members = Ext.apply({}, members);\r
21955 }\r
21956 if (statics) {\r
21957 me.addMembers(statics, true);\r
21958 delete members.statics;\r
21959 }\r
21960 if (inheritableStatics) {\r
21961 me.addInheritableStatics(inheritableStatics);\r
21962 delete members.inheritableStatics;\r
21963 }\r
21964 if (config) {\r
21965 me.addConfig(config);\r
21966 delete members.config;\r
21967 }\r
21968 if (cachedConfig) {\r
21969 me.addCachedConfig(cachedConfig);\r
21970 delete members.cachedConfig;\r
21971 }\r
21972 delete members.mixins;\r
21973 me.addMembers(members);\r
21974 if (mixins) {\r
21975 me.mixin(mixins);\r
21976 }\r
21977 return me;\r
21978 },\r
21979 /**
21980 * @protected
21981 * @static
21982 * @inheritable
21983 */\r
21984 callParent: function(args) {\r
21985 var method;\r
21986 // This code is intentionally inlined for the least amount of debugger stepping\r
21987 return (method = this.callParent.caller) && (method.$previous || ((method = method.$owner ? method : method.caller) && method.$owner.superclass.self[method.$name])).apply(this, args || noArgs);\r
21988 },\r
21989 /**
21990 * @protected
21991 * @static
21992 * @inheritable
21993 */\r
21994 callSuper: function(args) {\r
21995 var method;\r
21996 // This code is intentionally inlined for the least amount of debugger stepping\r
21997 return (method = this.callSuper.caller) && ((method = method.$owner ? method : method.caller) && method.$owner.superclass.self[method.$name]).apply(this, args || noArgs);\r
21998 },\r
21999 /**
22000 * Used internally by the mixins pre-processor
22001 * @private
22002 * @static
22003 * @inheritable
22004 */\r
22005 mixin: function(name, mixinClass) {\r
22006 var me = this,\r
22007 mixin, prototype, key, statics, i, ln, staticName, mixinValue, mixins;\r
22008 if (typeof name !== 'string') {\r
22009 mixins = name;\r
22010 if (mixins instanceof Array) {\r
22011 for (i = 0 , ln = mixins.length; i < ln; i++) {\r
22012 mixin = mixins[i];\r
22013 me.mixin(mixin.prototype.mixinId || mixin.$className, mixin);\r
22014 }\r
22015 } else {\r
22016 // Not a string or array - process the object form:\r
22017 // mixins: {\r
22018 // foo: ...\r
22019 // }\r
22020 for (var mixinName in mixins) {\r
22021 me.mixin(mixinName, mixins[mixinName]);\r
22022 }\r
22023 }\r
22024 return;\r
22025 }\r
22026 mixin = mixinClass.prototype;\r
22027 prototype = me.prototype;\r
22028 if (mixin.onClassMixedIn) {\r
22029 mixin.onClassMixedIn.call(mixinClass, me);\r
22030 }\r
22031 if (!prototype.hasOwnProperty('mixins')) {\r
22032 if ('mixins' in prototype) {\r
22033 prototype.mixins = Ext.Object.chain(prototype.mixins);\r
22034 } else {\r
22035 prototype.mixins = {};\r
22036 }\r
22037 }\r
22038 for (key in mixin) {\r
22039 mixinValue = mixin[key];\r
22040 if (key === 'mixins') {\r
22041 // if 2 superclasses (e.g. a base class and a mixin) of this class both\r
22042 // have a mixin with the same id, the first one wins, that is to say,\r
22043 // the first mixin's methods to be applied to the prototype will not\r
22044 // be overwritten by the second one. Since this is the case we also\r
22045 // want to make sure we use the first mixin's prototype as the mixin\r
22046 // reference, hence the "applyIf" below. A real world example of this\r
22047 // is Ext.Widget which mixes in Ext.mixin.Observable. Ext.Widget can\r
22048 // be mixed into subclasses of Ext.Component, which mixes in\r
22049 // Ext.util.Observable. In this example, since the first "observable"\r
22050 // mixin's methods win, we also want its reference to be preserved.\r
22051 Ext.applyIf(prototype.mixins, mixinValue);\r
22052 } else if (!(key === 'mixinId' || key === 'config') && (prototype[key] === undefined)) {\r
22053 prototype[key] = mixinValue;\r
22054 }\r
22055 }\r
22056 // Mixin statics inheritance\r
22057 statics = mixin.$inheritableStatics;\r
22058 if (statics) {\r
22059 for (i = 0 , ln = statics.length; i < ln; i++) {\r
22060 staticName = statics[i];\r
22061 if (!me.hasOwnProperty(staticName)) {\r
22062 me[staticName] = mixinClass[staticName];\r
22063 }\r
22064 }\r
22065 }\r
22066 if ('config' in mixin) {\r
22067 me.addConfig(mixin.config, mixinClass);\r
22068 }\r
22069 prototype.mixins[name] = mixin;\r
22070 if (mixin.afterClassMixedIn) {\r
22071 mixin.afterClassMixedIn.call(mixinClass, me);\r
22072 }\r
22073 return me;\r
22074 },\r
22075 /**
22076 * Adds new config properties to this class. This is called for classes when they
22077 * are declared, then for any mixins that class may define and finally for any
22078 * overrides defined that target the class.
22079 *
22080 * @param {Object} config
22081 * @param {Ext.Class} [mixinClass] The mixin class if the configs are from a mixin.
22082 * @private
22083 * @static
22084 * @inheritable
22085 */\r
22086 addConfig: function(config, mixinClass) {\r
22087 var cfg = this.$config || this.getConfigurator();\r
22088 cfg.add(config, mixinClass);\r
22089 },\r
22090 addCachedConfig: function(config, isMixin) {\r
22091 var cached = {},\r
22092 key;\r
22093 for (key in config) {\r
22094 cached[key] = {\r
22095 cached: true,\r
22096 $value: config[key]\r
22097 };\r
22098 }\r
22099 this.addConfig(cached, isMixin);\r
22100 },\r
22101 /**
22102 * Returns the `Ext.Configurator` for this class.
22103 *
22104 * @return {Ext.Configurator}
22105 * @private
22106 * @static
22107 * @inheritable
22108 */\r
22109 getConfigurator: function() {\r
22110 // the Ext.Configurator ctor will set $config so micro-opt out fn call:\r
22111 return this.$config || new Ext.Configurator(this);\r
22112 },\r
22113 /**
22114 * Get the current class' name in string format.
22115 *
22116 * Ext.define('My.cool.Class', {
22117 * constructor: function() {
22118 * alert(this.self.getName()); // alerts 'My.cool.Class'
22119 * }
22120 * });
22121 *
22122 * My.cool.Class.getName(); // 'My.cool.Class'
22123 *
22124 * @return {String} className
22125 * @static
22126 * @inheritable
22127 */\r
22128 getName: function() {\r
22129 return Ext.getClassName(this);\r
22130 },\r
22131 /**
22132 * Create aliases for existing prototype methods. Example:
22133 *
22134 * Ext.define('My.cool.Class', {
22135 * method1: function() { ... },
22136 * method2: function() { ... }
22137 * });
22138 *
22139 * var test = new My.cool.Class();
22140 *
22141 * My.cool.Class.createAlias({
22142 * method3: 'method1',
22143 * method4: 'method2'
22144 * });
22145 *
22146 * test.method3(); // test.method1()
22147 *
22148 * My.cool.Class.createAlias('method5', 'method3');
22149 *
22150 * test.method5(); // test.method3() -> test.method1()
22151 *
22152 * @param {String/Object} alias The new method name, or an object to set multiple aliases. See
22153 * {@link Ext.Function#flexSetter flexSetter}
22154 * @param {String/Object} origin The original method name
22155 * @static
22156 * @inheritable
22157 * @method
22158 */\r
22159 createAlias: flexSetter(function(alias, origin) {\r
22160 aliasOneMember[alias] = function() {\r
22161 return this[origin].apply(this, arguments);\r
22162 };\r
22163 this.override(aliasOneMember);\r
22164 delete aliasOneMember[alias];\r
22165 })\r
22166 });\r
22167 // Capture the set of static members on Ext.Base that we want to copy to all\r
22168 // derived classes. This array is used by Ext.Class as well as the optimizer.\r
22169 for (baseStaticMember in Base) {\r
22170 if (Base.hasOwnProperty(baseStaticMember)) {\r
22171 baseStaticMembers.push(baseStaticMember);\r
22172 }\r
22173 }\r
22174 Base.$staticMembers = baseStaticMembers;\r
22175 Base.getConfigurator();\r
22176 // lazily create now so as not capture in $staticMembers\r
22177 Base.addMembers({\r
22178 /** @private */\r
22179 $className: 'Ext.Base',\r
22180 /**
22181 * @property {Boolean} isInstance
22182 * This value is `true` and is used to identify plain objects from instances of
22183 * a defined class.
22184 * @protected
22185 * @readonly
22186 */\r
22187 isInstance: true,\r
22188 /**
22189 * @property {Boolean} [$configPrefixed]
22190 * The value `true` causes `config` values to be stored on instances using a
22191 * property name prefixed with an underscore ("_") character. A value of `false`
22192 * stores `config` values as properties using their exact name (no prefix).
22193 * @private
22194 * @since 5.0.0
22195 */\r
22196 $configPrefixed: true,\r
22197 /**
22198 * @property {Boolean} [$configStrict]
22199 * The value `true` instructs the `initConfig` method to only honor values for
22200 * properties declared in the `config` block of a class. When `false`, properties
22201 * that are not declared in a `config` block will be placed on the instance.
22202 * @private
22203 * @since 5.0.0
22204 */\r
22205 $configStrict: true,\r
22206 /**
22207 * @property {Boolean} isConfiguring
22208 * This property is set to `true` during the call to `initConfig`.
22209 * @protected
22210 * @readonly
22211 * @since 5.0.0
22212 */\r
22213 isConfiguring: false,\r
22214 /**
22215 * @property {Boolean} isFirstInstance
22216 * This property is set to `true` if this instance is the first of its class.
22217 * @protected
22218 * @readonly
22219 * @since 5.0.0
22220 */\r
22221 isFirstInstance: false,\r
22222 /**
22223 * @property {Boolean} destroyed
22224 * This property is set to `true` after the `destroy` method is called.
22225 * @protected
22226 */\r
22227 destroyed: false,\r
22228 /**
22229 * Get the reference to the class from which this object was instantiated. Note that unlike {@link Ext.Base#self},
22230 * `this.statics()` is scope-independent and it always returns the class from which it was called, regardless of what
22231 * `this` points to during run-time
22232 *
22233 * Ext.define('My.Cat', {
22234 * statics: {
22235 * totalCreated: 0,
22236 * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
22237 * },
22238 *
22239 * constructor: function() {
22240 * var statics = this.statics();
22241 *
22242 * alert(statics.speciesName); // always equals to 'Cat' no matter what 'this' refers to
22243 * // equivalent to: My.Cat.speciesName
22244 *
22245 * alert(this.self.speciesName); // dependent on 'this'
22246 *
22247 * statics.totalCreated++;
22248 * },
22249 *
22250 * clone: function() {
22251 * var cloned = new this.self(); // dependent on 'this'
22252 *
22253 * cloned.groupName = this.statics().speciesName; // equivalent to: My.Cat.speciesName
22254 *
22255 * return cloned;
22256 * }
22257 * });
22258 *
22259 *
22260 * Ext.define('My.SnowLeopard', {
22261 * extend: 'My.Cat',
22262 *
22263 * statics: {
22264 * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
22265 * },
22266 *
22267 * constructor: function() {
22268 * this.callParent();
22269 * }
22270 * });
22271 *
22272 * var cat = new My.Cat(); // alerts 'Cat', then alerts 'Cat'
22273 *
22274 * var snowLeopard = new My.SnowLeopard(); // alerts 'Cat', then alerts 'Snow Leopard'
22275 *
22276 * var clone = snowLeopard.clone();
22277 * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
22278 * alert(clone.groupName); // alerts 'Cat'
22279 *
22280 * alert(My.Cat.totalCreated); // alerts 3
22281 *
22282 * @protected
22283 * @return {Ext.Class}
22284 */\r
22285 statics: function() {\r
22286 var method = this.statics.caller,\r
22287 self = this.self;\r
22288 if (!method) {\r
22289 return self;\r
22290 }\r
22291 return method.$owner;\r
22292 },\r
22293 /**
22294 * Call the "parent" method of the current method. That is the method previously
22295 * overridden by derivation or by an override (see {@link Ext#define}).
22296 *
22297 * Ext.define('My.Base', {
22298 * constructor: function (x) {
22299 * this.x = x;
22300 * },
22301 *
22302 * statics: {
22303 * method: function (x) {
22304 * return x;
22305 * }
22306 * }
22307 * });
22308 *
22309 * Ext.define('My.Derived', {
22310 * extend: 'My.Base',
22311 *
22312 * constructor: function () {
22313 * this.callParent([21]);
22314 * }
22315 * });
22316 *
22317 * var obj = new My.Derived();
22318 *
22319 * alert(obj.x); // alerts 21
22320 *
22321 * This can be used with an override as follows:
22322 *
22323 * Ext.define('My.DerivedOverride', {
22324 * override: 'My.Derived',
22325 *
22326 * constructor: function (x) {
22327 * this.callParent([x*2]); // calls original My.Derived constructor
22328 * }
22329 * });
22330 *
22331 * var obj = new My.Derived();
22332 *
22333 * alert(obj.x); // now alerts 42
22334 *
22335 * This also works with static and private methods.
22336 *
22337 * Ext.define('My.Derived2', {
22338 * extend: 'My.Base',
22339 *
22340 * // privates: {
22341 * statics: {
22342 * method: function (x) {
22343 * return this.callParent([x*2]); // calls My.Base.method
22344 * }
22345 * }
22346 * });
22347 *
22348 * alert(My.Base.method(10)); // alerts 10
22349 * alert(My.Derived2.method(10)); // alerts 20
22350 *
22351 * Lastly, it also works with overridden static methods.
22352 *
22353 * Ext.define('My.Derived2Override', {
22354 * override: 'My.Derived2',
22355 *
22356 * // privates: {
22357 * statics: {
22358 * method: function (x) {
22359 * return this.callParent([x*2]); // calls My.Derived2.method
22360 * }
22361 * }
22362 * });
22363 *
22364 * alert(My.Derived2.method(10); // now alerts 40
22365 *
22366 * To override a method and replace it and also call the superclass method, use
22367 * {@link #method-callSuper}. This is often done to patch a method to fix a bug.
22368 *
22369 * @protected
22370 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
22371 * from the current method, for example: `this.callParent(arguments)`
22372 * @return {Object} Returns the result of calling the parent method
22373 */\r
22374 callParent: function(args) {\r
22375 // NOTE: this code is deliberately as few expressions (and no function calls)\r
22376 // as possible so that a debugger can skip over this noise with the minimum number\r
22377 // of steps. Basically, just hit Step Into until you are where you really wanted\r
22378 // to be.\r
22379 var method,\r
22380 superMethod = (method = this.callParent.caller) && (method.$previous || ((method = method.$owner ? method : method.caller) && method.$owner.superclass[method.$name]));\r
22381 if (!superMethod) {\r
22382 method = this.callParent.caller;\r
22383 var parentClass, methodName;\r
22384 if (!method.$owner) {\r
22385 if (!method.caller) {\r
22386 throw new Error("Attempting to call a protected method from the public scope, which is not allowed");\r
22387 }\r
22388 method = method.caller;\r
22389 }\r
22390 parentClass = method.$owner.superclass;\r
22391 methodName = method.$name;\r
22392 if (!(methodName in parentClass)) {\r
22393 throw new Error("this.callParent() was called but there's no such method (" + methodName + ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");\r
22394 }\r
22395 }\r
22396 return superMethod.apply(this, args || noArgs);\r
22397 },\r
22398 /**
22399 * This method is used by an **override** to call the superclass method but
22400 * bypass any overridden method. This is often done to "patch" a method that
22401 * contains a bug but for whatever reason cannot be fixed directly.
22402 *
22403 * Consider:
22404 *
22405 * Ext.define('Ext.some.Class', {
22406 * method: function () {
22407 * console.log('Good');
22408 * }
22409 * });
22410 *
22411 * Ext.define('Ext.some.DerivedClass', {
22412 * extend: 'Ext.some.Class',
22413 *
22414 * method: function () {
22415 * console.log('Bad');
22416 *
22417 * // ... logic but with a bug ...
22418 *
22419 * this.callParent();
22420 * }
22421 * });
22422 *
22423 * To patch the bug in `Ext.some.DerivedClass.method`, the typical solution is to create an
22424 * override:
22425 *
22426 * Ext.define('App.patches.DerivedClass', {
22427 * override: 'Ext.some.DerivedClass',
22428 *
22429 * method: function () {
22430 * console.log('Fixed');
22431 *
22432 * // ... logic but with bug fixed ...
22433 *
22434 * this.callSuper();
22435 * }
22436 * });
22437 *
22438 * The patch method cannot use {@link #method-callParent} to call the superclass
22439 * `method` since that would call the overridden method containing the bug. In
22440 * other words, the above patch would only produce "Fixed" then "Good" in the
22441 * console log, whereas, using `callParent` would produce "Fixed" then "Bad"
22442 * then "Good".
22443 *
22444 * @protected
22445 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
22446 * from the current method, for example: `this.callSuper(arguments)`
22447 * @return {Object} Returns the result of calling the superclass method
22448 */\r
22449 callSuper: function(args) {\r
22450 // NOTE: this code is deliberately as few expressions (and no function calls)\r
22451 // as possible so that a debugger can skip over this noise with the minimum number\r
22452 // of steps. Basically, just hit Step Into until you are where you really wanted\r
22453 // to be.\r
22454 var method,\r
22455 superMethod = (method = this.callSuper.caller) && ((method = method.$owner ? method : method.caller) && method.$owner.superclass[method.$name]);\r
22456 if (!superMethod) {\r
22457 method = this.callSuper.caller;\r
22458 var parentClass, methodName;\r
22459 if (!method.$owner) {\r
22460 if (!method.caller) {\r
22461 throw new Error("Attempting to call a protected method from the public scope, which is not allowed");\r
22462 }\r
22463 method = method.caller;\r
22464 }\r
22465 parentClass = method.$owner.superclass;\r
22466 methodName = method.$name;\r
22467 if (!(methodName in parentClass)) {\r
22468 throw new Error("this.callSuper() was called but there's no such method (" + methodName + ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");\r
22469 }\r
22470 }\r
22471 return superMethod.apply(this, args || noArgs);\r
22472 },\r
22473 /**
22474 * @property {Ext.Class} self
22475 *
22476 * Get the reference to the current class from which this object was instantiated. Unlike {@link Ext.Base#statics},
22477 * `this.self` is scope-dependent and it's meant to be used for dynamic inheritance. See {@link Ext.Base#statics}
22478 * for a detailed comparison
22479 *
22480 * Ext.define('My.Cat', {
22481 * statics: {
22482 * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'
22483 * },
22484 *
22485 * constructor: function() {
22486 * alert(this.self.speciesName); // dependent on 'this'
22487 * },
22488 *
22489 * clone: function() {
22490 * return new this.self();
22491 * }
22492 * });
22493 *
22494 *
22495 * Ext.define('My.SnowLeopard', {
22496 * extend: 'My.Cat',
22497 * statics: {
22498 * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'
22499 * }
22500 * });
22501 *
22502 * var cat = new My.Cat(); // alerts 'Cat'
22503 * var snowLeopard = new My.SnowLeopard(); // alerts 'Snow Leopard'
22504 *
22505 * var clone = snowLeopard.clone();
22506 * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'
22507 *
22508 * @protected
22509 */\r
22510 self: Base,\r
22511 // Default constructor, simply returns `this`\r
22512 constructor: function() {\r
22513 return this;\r
22514 },\r
22515 getConfigurator: function() {\r
22516 return this.$config || this.self.getConfigurator();\r
22517 },\r
22518 /**
22519 * Initialize configuration for this class. a typical example:
22520 *
22521 * Ext.define('My.awesome.Class', {
22522 * // The default config
22523 * config: {
22524 * name: 'Awesome',
22525 * isAwesome: true
22526 * },
22527 *
22528 * constructor: function(config) {
22529 * this.initConfig(config);
22530 * }
22531 * });
22532 *
22533 * var awesome = new My.awesome.Class({
22534 * name: 'Super Awesome'
22535 * });
22536 *
22537 * alert(awesome.getName()); // 'Super Awesome'
22538 *
22539 * @protected
22540 * @param {Object} config
22541 * @return {Ext.Base} this
22542 */\r
22543 initConfig: function(instanceConfig) {\r
22544 var me = this,\r
22545 cfg = me.getConfigurator();\r
22546 me.initConfig = Ext.emptyFn;\r
22547 // ignore subsequent calls to initConfig\r
22548 me.initialConfig = instanceConfig || {};\r
22549 cfg.configure(me, instanceConfig);\r
22550 return me;\r
22551 },\r
22552 beforeInitConfig: Ext.emptyFn,\r
22553 /**
22554 * Returns a specified config property value. If the name parameter is not passed,
22555 * all current configuration options will be returned as key value pairs.
22556 * @method
22557 * @param {String} [name] The name of the config property to get.
22558 * @param {Boolean} [peek=false] `true` to peek at the raw value without calling the getter.
22559 * @return {Object} The config property value.
22560 */\r
22561 getConfig: getConfig,\r
22562 /**
22563 * Sets a single/multiple configuration options.
22564 * @method
22565 * @param {String/Object} name The name of the property to set, or a set of key value pairs to set.
22566 * @param {Object} [value] The value to set for the name parameter.
22567 * @return {Ext.Base} this
22568 */\r
22569 setConfig: function(name, value, /* private */\r
22570 options) {\r
22571 // options can have the following properties:\r
22572 // - defaults `true` to only set the config(s) that have not been already set on\r
22573 // this instance.\r
22574 // - strict `false` to apply properties to the instance that are not configs,\r
22575 // and do not have setters.\r
22576 var me = this,\r
22577 config;\r
22578 if (name) {\r
22579 if (typeof name === 'string') {\r
22580 config = {};\r
22581 config[name] = value;\r
22582 } else {\r
22583 config = name;\r
22584 }\r
22585 me.getConfigurator().reconfigure(me, config, options);\r
22586 }\r
22587 return me;\r
22588 },\r
22589 /**
22590 * @private
22591 */\r
22592 getCurrentConfig: function() {\r
22593 var cfg = this.getConfigurator();\r
22594 return cfg.getCurrentConfig(this);\r
22595 },\r
22596 /**
22597 * @private
22598 * @param config
22599 */\r
22600 hasConfig: function(name) {\r
22601 return name in this.defaultConfig;\r
22602 },\r
22603 /**
22604 * Returns the initial configuration passed to the constructor when
22605 * instantiating this class.
22606 *
22607 * Given this example Ext.button.Button definition and instance:
22608 *
22609 * Ext.define('MyApp.view.Button', {
22610 * extend: 'Ext.button.Button',
22611 * xtype: 'mybutton',
22612 *
22613 * scale: 'large',
22614 * enableToggle: true
22615 * });
22616 *
22617 * var btn = Ext.create({
22618 * xtype: 'mybutton',
22619 * renderTo: Ext.getBody(),
22620 * text: 'Test Button'
22621 * });
22622 *
22623 * Calling `btn.getInitialConfig()` would return an object including the config
22624 * options passed to the `create` method:
22625 *
22626 * xtype: 'mybutton',
22627 * renderTo: // The document body itself
22628 * text: 'Test Button'
22629 *
22630 * Calling `btn.getInitialConfig('text')`returns **'Test Button'**.
22631 *
22632 * @param {String} [name] Name of the config option to return.
22633 * @return {Object/Mixed} The full config object or a single config value
22634 * when `name` parameter specified.
22635 */\r
22636 getInitialConfig: function(name) {\r
22637 var config = this.config;\r
22638 if (!name) {\r
22639 return config;\r
22640 }\r
22641 return config[name];\r
22642 },\r
22643 $links: null,\r
22644 /**
22645 * Adds a "destroyable" object to an internal list of objects that will be destroyed
22646 * when this instance is destroyed (via `{@link #destroy}`).
22647 * @param {String} name
22648 * @param {Object} value
22649 * @return {Object} The `value` passed.
22650 * @private
22651 */\r
22652 link: function(name, value) {\r
22653 var me = this,\r
22654 links = me.$links || (me.$links = {});\r
22655 links[name] = true;\r
22656 me[name] = value;\r
22657 return value;\r
22658 },\r
22659 /**
22660 * Destroys a given set of `{@link #link linked}` objects. This is only needed if
22661 * the linked object is being destroyed before this instance.
22662 * @param {String[]} names The names of the linked objects to destroy.
22663 * @return {Ext.Base} this
22664 * @private
22665 */\r
22666 unlink: function(names) {\r
22667 var me = this,\r
22668 i, ln, link, value;\r
22669 if (!Ext.isArray(names)) {\r
22670 Ext.raise('Invalid argument - expected array of strings');\r
22671 }\r
22672 for (i = 0 , ln = names.length; i < ln; i++) {\r
22673 link = names[i];\r
22674 value = me[link];\r
22675 if (value) {\r
22676 if (value.isInstance && !value.destroyed) {\r
22677 value.destroy();\r
22678 } else if (value.parentNode && 'nodeType' in value) {\r
22679 value.parentNode.removeChild(value);\r
22680 }\r
22681 }\r
22682 me[link] = null;\r
22683 }\r
22684 return me;\r
22685 },\r
22686 /**
22687 * This method is called to cleanup an object and its resources. After calling
22688 * this method, the object should not be used any further.
22689 */\r
22690 destroy: function() {\r
22691 var me = this,\r
22692 links = me.$links;\r
22693 me.initialConfig = me.config = null;\r
22694 me.destroy = Ext.emptyFn;\r
22695 // isDestroyed added for compat reasons\r
22696 me.isDestroyed = me.destroyed = true;\r
22697 if (links) {\r
22698 me.$links = null;\r
22699 me.unlink(Ext.Object.getKeys(links));\r
22700 }\r
22701 }\r
22702 });\r
22703 /**
22704 * Call the original method that was previously overridden with {@link Ext.Base#override}
22705 *
22706 * Ext.define('My.Cat', {
22707 * constructor: function() {
22708 * alert("I'm a cat!");
22709 * }
22710 * });
22711 *
22712 * My.Cat.override({
22713 * constructor: function() {
22714 * alert("I'm going to be a cat!");
22715 *
22716 * this.callOverridden();
22717 *
22718 * alert("Meeeeoooowwww");
22719 * }
22720 * });
22721 *
22722 * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"
22723 * // alerts "I'm a cat!"
22724 * // alerts "Meeeeoooowwww"
22725 *
22726 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object
22727 * from the current method, for example: `this.callOverridden(arguments)`
22728 * @return {Object} Returns the result of calling the overridden method
22729 * @protected
22730 * @deprecated Use {@link #callParent} instead.
22731 */\r
22732 BasePrototype.callOverridden = BasePrototype.callParent;\r
22733 Ext.privacyViolation = function(cls, existing, member, isStatic) {\r
22734 var name = member.$name,\r
22735 conflictCls = existing.$owner && existing.$owner.$className,\r
22736 s = isStatic ? 'static ' : '',\r
22737 msg = member.$privacy ? 'Private ' + s + member.$privacy + ' method "' + name + '"' : 'Public ' + s + 'method "' + name + '"';\r
22738 if (cls.$className) {\r
22739 msg = cls.$className + ': ' + msg;\r
22740 }\r
22741 if (!existing.$privacy) {\r
22742 msg += conflictCls ? ' hides public method inherited from ' + conflictCls : ' hides inherited public method.';\r
22743 } else {\r
22744 msg += conflictCls ? ' conflicts with private ' + existing.$privacy + ' method declared by ' + conflictCls : ' conflicts with inherited private ' + existing.$privacy + ' method.';\r
22745 }\r
22746 var compat = Ext.getCompatVersion();\r
22747 var ver = Ext.getVersion();\r
22748 // When compatibility is enabled, log problems instead of throwing errors.\r
22749 if (ver && compat && compat.lt(ver)) {\r
22750 Ext.log.error(msg);\r
22751 } else {\r
22752 Ext.raise(msg);\r
22753 }\r
22754 };\r
22755 return Base;\r
22756}(Ext.Function.flexSetter));\r
22757\r
22758/**
22759 * This class is used to manage simple, LRU caches. It provides an absolutely minimal
22760 * container interface. It is created like this:
22761 *
22762 * this.itemCache = new Ext.util.Cache({
22763 * miss: function (key) {
22764 * return new CacheItem(key);
22765 * }
22766 * });
22767 *
22768 * The `{@link #miss}` abstract method must be implemented by either a derived class or
22769 * at the instance level as shown above.
22770 *
22771 * Once the cache exists and it can handle cache misses, the cache is used like so:
22772 *
22773 * var item = this.itemCache.get(key);
22774 *
22775 * The `key` is some value that uniquely identifies the cached item.
22776 *
22777 * In some cases, creating the cache item may require more than just the lookup key. In
22778 * that case, any extra arguments passed to `get` will be passed to `miss`.
22779 *
22780 * this.otherCache = new Ext.util.Cache({
22781 * miss: function (key, extra) {
22782 * return new CacheItem(key, extra);
22783 * }
22784 * });
22785 *
22786 * var item = this.otherCache.get(key, extra);
22787 *
22788 * To process items as they are removed, you can provide an `{@link #evict}` method. The
22789 * stock method is `Ext.emptyFn` and so does nothing.
22790 *
22791 * For example:
22792 *
22793 * this.itemCache = new Ext.util.Cache({
22794 * miss: function (key) {
22795 * return new CacheItem(key);
22796 * },
22797 *
22798 * evict: function (key, cacheItem) {
22799 * cacheItem.destroy();
22800 * }
22801 * });
22802 *
22803 * @class Ext.util.Cache
22804 * @private
22805 * @since 5.1.0
22806 */\r
22807(function(Cache, prototype) {\r
22808 // @define Ext.util.Cache\r
22809 // NOTE: We have to implement this class old-school because it is used by the\r
22810 // platformConfig class processor (so Ext.define is not yet ready for action).\r
22811 (Ext.util || (Ext.util = {})).Cache = Cache = function(config) {\r
22812 var me = this,\r
22813 head;\r
22814 if (config) {\r
22815 Ext.apply(me, config);\r
22816 }\r
22817 // Give all entries the same object shape.\r
22818 me.head = head = {\r
22819 id: (me.seed = 0),\r
22820 key: null,\r
22821 value: null\r
22822 };\r
22823 me.map = {};\r
22824 head.next = head.prev = head;\r
22825 };\r
22826 Cache.prototype = prototype = {\r
22827 /**
22828 * @cfg {Number} maxSize The maximum size the cache is allowed to grow to before
22829 * further additions cause removal of the least recently used entry.
22830 */\r
22831 maxSize: 100,\r
22832 /**
22833 * @property {Number} count
22834 * The number of items in this cache.
22835 * @readonly
22836 */\r
22837 count: 0,\r
22838 /**
22839 * This method is called by `{@link #get}` when the key is not found in the cache.
22840 * The implementation of this method should create the (expensive) value and return
22841 * it. Whatever arguments were passed to `{@link #get}` will be passed on to this
22842 * method.
22843 *
22844 * @param {String} key The cache lookup key for the item.
22845 * @param {Object...} args Any other arguments originally passed to `{@link #get}`.
22846 * @method miss
22847 * @abstract
22848 * @protected
22849 */\r
22850 /**
22851 * Removes all items from this cache.
22852 */\r
22853 clear: function() {\r
22854 var me = this,\r
22855 head = me.head,\r
22856 entry = head.next;\r
22857 head.next = head.prev = head;\r
22858 if (!me.evict.$nullFn) {\r
22859 for (; entry !== head; entry = entry.next) {\r
22860 me.evict(entry.key, entry.value);\r
22861 }\r
22862 }\r
22863 me.count = 0;\r
22864 },\r
22865 /**
22866 * Calls the given function `fn` for each item in the cache. The items will be passed
22867 * to `fn` from most-to-least recently used.
22868 * @param {Function} fn The function to call for each cache item.
22869 * @param {String} fn.key The cache key for the item.
22870 * @param {Object} fn.value The value in the cache for the item.
22871 * @param {Object} [scope] The `this` pointer to use for `fn`.
22872 */\r
22873 each: function(fn, scope) {\r
22874 scope = scope || this;\r
22875 for (var head = this.head,\r
22876 ent = head.next; ent !== head; ent = ent.next) {\r
22877 if (fn.call(scope, ent.key, ent.value)) {\r
22878 break;\r
22879 }\r
22880 }\r
22881 },\r
22882 /**
22883 * Finds an item in this cache and returns its value. If the item is present, it is
22884 * shuffled into the MRU (most-recently-used) position as necessary. If the item is
22885 * missing, the `{@link #miss}` method is called to create the item.
22886 *
22887 * @param {String} key The cache key of the item.
22888 * @param {Object...} args Arguments for the `miss` method should it be needed.
22889 * @return {Object} The cached object.
22890 */\r
22891 get: function(key) {\r
22892 var me = this,\r
22893 head = me.head,\r
22894 map = me.map,\r
22895 entry = map[key];\r
22896 if (entry) {\r
22897 if (entry.prev !== head) {\r
22898 // The entry is not at the front, so remove it and insert it at the front\r
22899 // (to make it the MRU - Most Recently Used).\r
22900 me.unlinkEntry(entry);\r
22901 me.linkEntry(entry);\r
22902 }\r
22903 } else {\r
22904 map[key] = entry = {\r
22905 id: ++me.seed,\r
22906 key: key,\r
22907 value: me.miss.apply(me, arguments)\r
22908 };\r
22909 me.linkEntry(entry);\r
22910 ++me.count;\r
22911 while (me.count > me.maxSize) {\r
22912 me.unlinkEntry(head.prev, true);\r
22913 --me.count;\r
22914 }\r
22915 }\r
22916 return entry.value;\r
22917 },\r
22918 //-------------------------------------------------------------------------\r
22919 // Internals\r
22920 /**
22921 * This method is called internally from `{@link #get}` when the cache is full and
22922 * the least-recently-used (LRU) item has been removed.
22923 *
22924 * @param {String} key The cache lookup key for the item being removed.
22925 * @param {Object} value The cache value (returned by `{@link #miss}`) for the item
22926 * being removed.
22927 * @method evict
22928 * @template
22929 * @protected
22930 */\r
22931 evict: Ext.emptyFn,\r
22932 /**
22933 * Inserts the given entry at the front (MRU) end of the entry list.
22934 * @param {Object} entry The cache item entry.
22935 * @private
22936 */\r
22937 linkEntry: function(entry) {\r
22938 var head = this.head,\r
22939 first = head.next;\r
22940 entry.next = first;\r
22941 entry.prev = head;\r
22942 head.next = entry;\r
22943 first.prev = entry;\r
22944 },\r
22945 /**
22946 * Removes the given entry from the entry list.
22947 * @param {Object} entry The cache item entry.
22948 * @param {Boolean} evicted Pass `true` if `{@link #evict}` should be called.
22949 * @private
22950 */\r
22951 unlinkEntry: function(entry, evicted) {\r
22952 var next = entry.next,\r
22953 prev = entry.prev;\r
22954 prev.next = next;\r
22955 next.prev = prev;\r
22956 if (evicted) {\r
22957 this.evict(entry.key, entry.value);\r
22958 }\r
22959 }\r
22960 };\r
22961 prototype.destroy = prototype.clear;\r
22962}());\r
22963\r
22964/**
22965 * @class Ext.Class
22966 *
22967 * This is a low level factory that is used by {@link Ext#define Ext.define} and should not be used
22968 * directly in application code.
22969 *
22970 * The configs of this class are intended to be used in `Ext.define` calls to describe the class you
22971 * are declaring. For example:
22972 *
22973 * Ext.define('App.util.Thing', {
22974 * extend: 'App.util.Other',
22975 *
22976 * alias: 'util.thing',
22977 *
22978 * config: {
22979 * foo: 42
22980 * }
22981 * });
22982 *
22983 * Ext.Class is the factory and **not** the superclass of everything. For the base class that **all**
22984 * classes inherit from, see {@link Ext.Base}.
22985 */\r
22986(function() {\r
22987 // @tag class\r
22988 // @define Ext.Class\r
22989 // @require Ext.Base\r
22990 // @require Ext.Util\r
22991 // @require Ext.util.Cache\r
22992 var ExtClass,\r
22993 Base = Ext.Base,\r
22994 baseStaticMembers = Base.$staticMembers,\r
22995 ruleKeySortFn = function(a, b) {\r
22996 // longest to shortest, by text if names are equal\r
22997 return (a.length - b.length) || ((a < b) ? -1 : ((a > b) ? 1 : 0));\r
22998 };\r
22999 // Creates a constructor that has nothing extra in its scope chain.\r
23000 function makeCtor(className) {\r
23001 function constructor() {\r
23002 // Opera has some problems returning from a constructor when Dragonfly isn't running. The || null seems to\r
23003 // be sufficient to stop it misbehaving. Known to be required against 10.53, 11.51 and 11.61.\r
23004 return this.constructor.apply(this, arguments) || null;\r
23005 }\r
23006 if (className) {\r
23007 constructor.name = className;\r
23008 }\r
23009 return constructor;\r
23010 }\r
23011 /**
23012 * @method constructor
23013 * Create a new anonymous class.
23014 *
23015 * @param {Object} data An object represent the properties of this class
23016 * @param {Function} onCreated Optional, the callback function to be executed when this class is fully created.
23017 * Note that the creation process can be asynchronous depending on the pre-processors used.
23018 *
23019 * @return {Ext.Base} The newly created class
23020 */\r
23021 Ext.Class = ExtClass = function(Class, data, onCreated) {\r
23022 if (typeof Class != 'function') {\r
23023 onCreated = data;\r
23024 data = Class;\r
23025 Class = null;\r
23026 }\r
23027 if (!data) {\r
23028 data = {};\r
23029 }\r
23030 Class = ExtClass.create(Class, data);\r
23031 ExtClass.process(Class, data, onCreated);\r
23032 return Class;\r
23033 };\r
23034 Ext.apply(ExtClass, {\r
23035 makeCtor: makeCtor,\r
23036 /**
23037 * @private
23038 */\r
23039 onBeforeCreated: function(Class, data, hooks) {\r
23040 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, '>> Ext.Class#onBeforeCreated', arguments);\r
23041 Class.addMembers(data);\r
23042 hooks.onCreated.call(Class, Class);\r
23043 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, '<< Ext.Class#onBeforeCreated', arguments);\r
23044 },\r
23045 /**
23046 * @private
23047 */\r
23048 create: function(Class, data) {\r
23049 var i = baseStaticMembers.length,\r
23050 name;\r
23051 if (!Class) {\r
23052 Class = makeCtor(data.$className);\r
23053 }\r
23054 while (i--) {\r
23055 name = baseStaticMembers[i];\r
23056 Class[name] = Base[name];\r
23057 }\r
23058 return Class;\r
23059 },\r
23060 /**
23061 * @private
23062 */\r
23063 process: function(Class, data, onCreated) {\r
23064 var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors,\r
23065 registeredPreprocessors = this.preprocessors,\r
23066 hooks = {\r
23067 onBeforeCreated: this.onBeforeCreated\r
23068 },\r
23069 preprocessors = [],\r
23070 preprocessor, preprocessorsProperties, i, ln, j, subLn, preprocessorProperty;\r
23071 delete data.preprocessors;\r
23072 Class._classHooks = hooks;\r
23073 for (i = 0 , ln = preprocessorStack.length; i < ln; i++) {\r
23074 preprocessor = preprocessorStack[i];\r
23075 if (typeof preprocessor == 'string') {\r
23076 preprocessor = registeredPreprocessors[preprocessor];\r
23077 preprocessorsProperties = preprocessor.properties;\r
23078 if (preprocessorsProperties === true) {\r
23079 preprocessors.push(preprocessor.fn);\r
23080 } else if (preprocessorsProperties) {\r
23081 for (j = 0 , subLn = preprocessorsProperties.length; j < subLn; j++) {\r
23082 preprocessorProperty = preprocessorsProperties[j];\r
23083 if (data.hasOwnProperty(preprocessorProperty)) {\r
23084 preprocessors.push(preprocessor.fn);\r
23085 break;\r
23086 }\r
23087 }\r
23088 }\r
23089 } else {\r
23090 preprocessors.push(preprocessor);\r
23091 }\r
23092 }\r
23093 hooks.onCreated = onCreated ? onCreated : Ext.emptyFn;\r
23094 hooks.preprocessors = preprocessors;\r
23095 this.doProcess(Class, data, hooks);\r
23096 },\r
23097 doProcess: function(Class, data, hooks) {\r
23098 var me = this,\r
23099 preprocessors = hooks.preprocessors,\r
23100 preprocessor = preprocessors.shift(),\r
23101 doProcess = me.doProcess;\r
23102 for (; preprocessor; preprocessor = preprocessors.shift()) {\r
23103 // Returning false signifies an asynchronous preprocessor - it will call doProcess when we can continue\r
23104 if (preprocessor.call(me, Class, data, hooks, doProcess) === false) {\r
23105 return;\r
23106 }\r
23107 }\r
23108 hooks.onBeforeCreated.apply(me, arguments);\r
23109 },\r
23110 /**
23111 * @private
23112 * */\r
23113 preprocessors: {},\r
23114 /**
23115 * Register a new pre-processor to be used during the class creation process
23116 *
23117 * @param {String} name The pre-processor's name
23118 * @param {Function} fn The callback function to be executed. Typical format:
23119 *
23120 * function(cls, data, fn) {
23121 * // Your code here
23122 *
23123 * // Execute this when the processing is finished.
23124 * // Asynchronous processing is perfectly ok
23125 * if (fn) {
23126 * fn.call(this, cls, data);
23127 * }
23128 * });
23129 *
23130 * @param {Function} fn.cls The created class
23131 * @param {Object} fn.data The set of properties passed in {@link Ext.Class} constructor
23132 * @param {Function} fn.fn The callback function that **must** to be executed when this
23133 * pre-processor finishes, regardless of whether the processing is synchronous or asynchronous.
23134 * @return {Ext.Class} this
23135 * @private
23136 * @static
23137 */\r
23138 registerPreprocessor: function(name, fn, properties, position, relativeTo) {\r
23139 if (!position) {\r
23140 position = 'last';\r
23141 }\r
23142 if (!properties) {\r
23143 properties = [\r
23144 name\r
23145 ];\r
23146 }\r
23147 this.preprocessors[name] = {\r
23148 name: name,\r
23149 properties: properties || false,\r
23150 fn: fn\r
23151 };\r
23152 this.setDefaultPreprocessorPosition(name, position, relativeTo);\r
23153 return this;\r
23154 },\r
23155 /**
23156 * Retrieve a pre-processor callback function by its name, which has been registered before
23157 *
23158 * @param {String} name
23159 * @return {Function} preprocessor
23160 * @private
23161 * @static
23162 */\r
23163 getPreprocessor: function(name) {\r
23164 return this.preprocessors[name];\r
23165 },\r
23166 /**
23167 * @private
23168 */\r
23169 getPreprocessors: function() {\r
23170 return this.preprocessors;\r
23171 },\r
23172 /**
23173 * @private
23174 */\r
23175 defaultPreprocessors: [],\r
23176 /**
23177 * Retrieve the array stack of default pre-processors
23178 * @return {Function[]} defaultPreprocessors
23179 * @private
23180 * @static
23181 */\r
23182 getDefaultPreprocessors: function() {\r
23183 return this.defaultPreprocessors;\r
23184 },\r
23185 /**
23186 * Set the default array stack of default pre-processors
23187 *
23188 * @private
23189 * @param {Array} preprocessors
23190 * @return {Ext.Class} this
23191 * @static
23192 */\r
23193 setDefaultPreprocessors: function(preprocessors) {\r
23194 this.defaultPreprocessors = Ext.Array.from(preprocessors);\r
23195 return this;\r
23196 },\r
23197 /**
23198 * Insert this pre-processor at a specific position in the stack, optionally relative to
23199 * any existing pre-processor. For example:
23200 *
23201 * Ext.Class.registerPreprocessor('debug', function(cls, data, fn) {
23202 * // Your code here
23203 *
23204 * if (fn) {
23205 * fn.call(this, cls, data);
23206 * }
23207 * }).setDefaultPreprocessorPosition('debug', 'last');
23208 *
23209 * @private
23210 * @param {String} name The pre-processor name. Note that it needs to be registered with
23211 * {@link Ext.Class#registerPreprocessor registerPreprocessor} before this
23212 * @param {String} offset The insertion position. Four possible values are:
23213 * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
23214 * @param {String} relativeName
23215 * @return {Ext.Class} this
23216 * @static
23217 */\r
23218 setDefaultPreprocessorPosition: function(name, offset, relativeName) {\r
23219 var defaultPreprocessors = this.defaultPreprocessors,\r
23220 index;\r
23221 if (typeof offset == 'string') {\r
23222 if (offset === 'first') {\r
23223 defaultPreprocessors.unshift(name);\r
23224 return this;\r
23225 } else if (offset === 'last') {\r
23226 defaultPreprocessors.push(name);\r
23227 return this;\r
23228 }\r
23229 offset = (offset === 'after') ? 1 : -1;\r
23230 }\r
23231 index = Ext.Array.indexOf(defaultPreprocessors, relativeName);\r
23232 if (index !== -1) {\r
23233 Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);\r
23234 }\r
23235 return this;\r
23236 }\r
23237 });\r
23238 /**
23239 * @cfg {String} extend
23240 * The parent class that this class extends. For example:
23241 *
23242 * Ext.define('Person', {
23243 * say: function(text) { alert(text); }
23244 * });
23245 *
23246 * Ext.define('Developer', {
23247 * extend: 'Person',
23248 * say: function(text) { this.callParent(["print "+text]); }
23249 * });
23250 */\r
23251 ExtClass.registerPreprocessor('extend', function(Class, data, hooks) {\r
23252 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#extendPreProcessor', arguments);\r
23253 var Base = Ext.Base,\r
23254 basePrototype = Base.prototype,\r
23255 extend = data.extend,\r
23256 Parent, parentPrototype, i;\r
23257 delete data.extend;\r
23258 if (extend && extend !== Object) {\r
23259 Parent = extend;\r
23260 } else {\r
23261 Parent = Base;\r
23262 }\r
23263 parentPrototype = Parent.prototype;\r
23264 if (!Parent.$isClass) {\r
23265 for (i in basePrototype) {\r
23266 if (!parentPrototype[i]) {\r
23267 parentPrototype[i] = basePrototype[i];\r
23268 }\r
23269 }\r
23270 }\r
23271 Class.extend(Parent);\r
23272 Class.triggerExtended.apply(Class, arguments);\r
23273 if (data.onClassExtended) {\r
23274 Class.onExtended(data.onClassExtended, Class);\r
23275 delete data.onClassExtended;\r
23276 }\r
23277 }, true);\r
23278 // true to always run this preprocessor even w/o "extend" keyword\r
23279 /**
23280 * @cfg {Object} privates
23281 * The `privates` config is a list of methods intended to be used internally by the
23282 * framework. Methods are placed in a `privates` block to prevent developers from
23283 * accidentally overriding framework methods in custom classes.
23284 *
23285 * Ext.define('Computer', {
23286 * privates: {
23287 * runFactory: function(brand) {
23288 * // internal only processing of brand passed to factory
23289 * this.factory(brand);
23290 * }
23291 * },
23292 *
23293 * factory: function (brand) {}
23294 * });
23295 *
23296 * In order to override a method from a `privates` block, the overridden method must
23297 * also be placed in a `privates` block within the override class.
23298 *
23299 * Ext.define('Override.Computer', {
23300 * override: 'Computer',
23301 * privates: {
23302 * runFactory: function() {
23303 * // overriding logic
23304 * }
23305 * }
23306 * });
23307 */\r
23308 ExtClass.registerPreprocessor('privates', function(Class, data) {\r
23309 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#privatePreprocessor', arguments);\r
23310 var privates = data.privates,\r
23311 statics = privates.statics,\r
23312 privacy = privates.privacy || true;\r
23313 delete data.privates;\r
23314 delete privates.statics;\r
23315 // We have to add this preprocessor so that private getters/setters are picked up\r
23316 // by the config system. This also catches duplication in the public part of the\r
23317 // class since it is an error to override a private method with a public one.\r
23318 Class.addMembers(privates, false, privacy);\r
23319 if (statics) {\r
23320 Class.addMembers(statics, true, privacy);\r
23321 }\r
23322 });\r
23323 /**
23324 * @cfg {Object} statics
23325 * List of static methods for this class. For example:
23326 *
23327 * Ext.define('Computer', {
23328 * statics: {
23329 * factory: function(brand) {
23330 * // 'this' in static methods refer to the class itself
23331 * return new this(brand);
23332 * }
23333 * },
23334 *
23335 * constructor: function() { ... }
23336 * });
23337 *
23338 * var dellComputer = Computer.factory('Dell');
23339 */\r
23340 ExtClass.registerPreprocessor('statics', function(Class, data) {\r
23341 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#staticsPreprocessor', arguments);\r
23342 Class.addStatics(data.statics);\r
23343 delete data.statics;\r
23344 });\r
23345 /**
23346 * @cfg {Object} inheritableStatics
23347 * List of inheritable static methods for this class.
23348 * Otherwise just like {@link #statics} but subclasses inherit these methods.
23349 */\r
23350 ExtClass.registerPreprocessor('inheritableStatics', function(Class, data) {\r
23351 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#inheritableStaticsPreprocessor', arguments);\r
23352 Class.addInheritableStatics(data.inheritableStatics);\r
23353 delete data.inheritableStatics;\r
23354 });\r
23355 Ext.createRuleFn = function(code) {\r
23356 return new Function('$c', 'with($c) { return (' + code + '); }');\r
23357 };\r
23358 Ext.expressionCache = new Ext.util.Cache({\r
23359 miss: Ext.createRuleFn\r
23360 });\r
23361 Ext.ruleKeySortFn = ruleKeySortFn;\r
23362 Ext.getPlatformConfigKeys = function(platformConfig) {\r
23363 var ret = [],\r
23364 platform, rule;\r
23365 for (platform in platformConfig) {\r
23366 rule = Ext.expressionCache.get(platform);\r
23367 if (rule(Ext.platformTags)) {\r
23368 ret.push(platform);\r
23369 }\r
23370 }\r
23371 ret.sort(ruleKeySortFn);\r
23372 return ret;\r
23373 };\r
23374 /**
23375 * @cfg {Object} platformConfig
23376 * Allows setting config values for a class based on specific platforms. The value
23377 * of this config is an object whose properties are "rules" and whose values are
23378 * objects containing config values.
23379 *
23380 * For example:
23381 *
23382 * Ext.define('App.view.Foo', {
23383 * extend: 'Ext.panel.Panel',
23384 *
23385 * platformConfig: {
23386 * desktop: {
23387 * title: 'Some Rather Descriptive Title'
23388 * },
23389 *
23390 * '!desktop': {
23391 * title: 'Short Title'
23392 * }
23393 * }
23394 * });
23395 *
23396 * In the above, "desktop" and "!desktop" are (mutually exclusive) rules. Whichever
23397 * evaluates to `true` will have its configs applied to the class. In this case, only
23398 * the "title" property, but the object can contain any number of config properties.
23399 * In this case, the `platformConfig` is evaluated as part of the class and there is
23400 * not cost for each instance created.
23401 *
23402 * The rules are evaluated expressions in the context of the platform tags contained
23403 * in `{@link Ext#platformTags Ext.platformTags}`. Any properties of that object are
23404 * implicitly usable (as shown above).
23405 *
23406 * If a `platformConfig` specifies a config value, it will replace any values declared
23407 * on the class itself.
23408 *
23409 * Use of `platformConfig` on instances is handled by the config system when classes
23410 * call `{@link Ext.Base#initConfig initConfig}`. For example:
23411 *
23412 * Ext.create({
23413 * xtype: 'panel',
23414 *
23415 * platformConfig: {
23416 * desktop: {
23417 * title: 'Some Rather Descriptive Title'
23418 * },
23419 *
23420 * '!desktop': {
23421 * title: 'Short Title'
23422 * }
23423 * }
23424 * });
23425 *
23426 * The following is equivalent to the above:
23427 *
23428 * if (Ext.platformTags.desktop) {
23429 * Ext.create({
23430 * xtype: 'panel',
23431 * title: 'Some Rather Descriptive Title'
23432 * });
23433 * } else {
23434 * Ext.create({
23435 * xtype: 'panel',
23436 * title: 'Short Title'
23437 * });
23438 * }
23439 *
23440 * To adjust configs based on dynamic conditions, see `{@link Ext.mixin.Responsive}`.
23441 */\r
23442 ExtClass.registerPreprocessor('platformConfig', function(Class, data, hooks) {\r
23443 var platformConfigs = data.platformConfig,\r
23444 config = data.config,\r
23445 added, classConfigs, configs, configurator, hoisted, keys, name, value, i, ln;\r
23446 delete data.platformConfig;\r
23447 if (platformConfigs instanceof Array) {\r
23448 throw new Error('platformConfigs must be specified as an object.');\r
23449 }\r
23450 configurator = Class.getConfigurator();\r
23451 classConfigs = configurator.configs;\r
23452 // Get the keys shortest to longest (ish).\r
23453 keys = Ext.getPlatformConfigKeys(platformConfigs);\r
23454 // To leverage the Configurator#add method, we want to generate potentially\r
23455 // two objects to pass in: "added" and "hoisted". For any properties in an\r
23456 // active platformConfig rule that set proper Configs in the base class, we\r
23457 // need to put them in "added". If instead of the proper Config coming from\r
23458 // a base class, it comes from this class's config block, we still need to\r
23459 // put that config in "added" but we also need move the class-level config\r
23460 // out of "config" and into "hoisted".\r
23461 //\r
23462 // This will ensure that the config defined at the class level is added to\r
23463 // the Configurator first.\r
23464 for (i = 0 , ln = keys.length; i < ln; ++i) {\r
23465 configs = platformConfigs[keys[i]];\r
23466 hoisted = added = null;\r
23467 for (name in configs) {\r
23468 value = configs[name];\r
23469 // We have a few possibilities for each config name:\r
23470 if (config && name in config) {\r
23471 // It is a proper Config defined by this class.\r
23472 (added || (added = {}))[name] = value;\r
23473 (hoisted || (hoisted = {}))[name] = config[name];\r
23474 delete config[name];\r
23475 } else if (name in classConfigs) {\r
23476 // It is a proper Config defined by a base class.\r
23477 (added || (added = {}))[name] = value;\r
23478 } else {\r
23479 // It is just a property to put on the prototype.\r
23480 data[name] = value;\r
23481 }\r
23482 }\r
23483 if (hoisted) {\r
23484 configurator.add(hoisted);\r
23485 }\r
23486 if (added) {\r
23487 configurator.add(added);\r
23488 }\r
23489 }\r
23490 });\r
23491 /**
23492 * @cfg {Object} config
23493 *
23494 * List of configuration options with their default values.
23495 *
23496 * __Note:__ You need to make sure {@link Ext.Base#initConfig} is called from your constructor if you are defining
23497 * your own class or singleton, unless you are extending a Component. Otherwise the generated getter and setter
23498 * methods will not be initialized.
23499 *
23500 * Each config item will have its own setter and getter method automatically generated inside the class prototype
23501 * during class creation time, if the class does not have those methods explicitly defined.
23502 *
23503 * As an example, let's convert the name property of a Person class to be a config item, then add extra age and
23504 * gender items.
23505 *
23506 * Ext.define('My.sample.Person', {
23507 * config: {
23508 * name: 'Mr. Unknown',
23509 * age: 0,
23510 * gender: 'Male'
23511 * },
23512 *
23513 * constructor: function(config) {
23514 * this.initConfig(config);
23515 *
23516 * return this;
23517 * }
23518 *
23519 * // ...
23520 * });
23521 *
23522 * Within the class, this.name still has the default value of "Mr. Unknown". However, it's now publicly accessible
23523 * without sacrificing encapsulation, via setter and getter methods.
23524 *
23525 * var jacky = new Person({
23526 * name: "Jacky",
23527 * age: 35
23528 * });
23529 *
23530 * alert(jacky.getAge()); // alerts 35
23531 * alert(jacky.getGender()); // alerts "Male"
23532 *
23533 * jacky.walk(10); // alerts "Jacky is walking 10 steps"
23534 *
23535 * jacky.setName("Mr. Nguyen");
23536 * alert(jacky.getName()); // alerts "Mr. Nguyen"
23537 *
23538 * jacky.walk(10); // alerts "Mr. Nguyen is walking 10 steps"
23539 *
23540 * Notice that we changed the class constructor to invoke this.initConfig() and pass in the provided config object.
23541 * Two key things happened:
23542 *
23543 * - The provided config object when the class is instantiated is recursively merged with the default config object.
23544 * - All corresponding setter methods are called with the merged values.
23545 *
23546 * Beside storing the given values, throughout the frameworks, setters generally have two key responsibilities:
23547 *
23548 * - Filtering / validation / transformation of the given value before it's actually stored within the instance.
23549 * - Notification (such as firing events) / post-processing after the value has been set, or changed from a
23550 * previous value.
23551 *
23552 * By standardize this common pattern, the default generated setters provide two extra template methods that you
23553 * can put your own custom logics into, i.e: an "applyFoo" and "updateFoo" method for a "foo" config item, which are
23554 * executed before and after the value is actually set, respectively. Back to the example class, let's validate that
23555 * age must be a valid positive number, and fire an 'agechange' if the value is modified.
23556 *
23557 * Ext.define('My.sample.Person', {
23558 * config: {
23559 * // ...
23560 * },
23561 *
23562 * constructor: {
23563 * // ...
23564 * },
23565 *
23566 * applyAge: function(age) {
23567 * if (typeof age !== 'number' || age < 0) {
23568 * console.warn("Invalid age, must be a positive number");
23569 * return;
23570 * }
23571 *
23572 * return age;
23573 * },
23574 *
23575 * updateAge: function(newAge, oldAge) {
23576 * // age has changed from "oldAge" to "newAge"
23577 * this.fireEvent('agechange', this, newAge, oldAge);
23578 * }
23579 *
23580 * // ...
23581 * });
23582 *
23583 * var jacky = new Person({
23584 * name: "Jacky",
23585 * age: 'invalid'
23586 * });
23587 *
23588 * alert(jacky.getAge()); // alerts 0
23589 *
23590 * alert(jacky.setAge(-100)); // alerts 0
23591 * alert(jacky.getAge()); // alerts 0
23592 *
23593 * alert(jacky.setAge(35)); // alerts 0
23594 * alert(jacky.getAge()); // alerts 35
23595 *
23596 * In other words, when leveraging the config feature, you mostly never need to define setter and getter methods
23597 * explicitly. Instead, "apply*" and "update*" methods should be implemented where necessary. Your code will be
23598 * consistent throughout and only contain the minimal logic that you actually care about.
23599 *
23600 * When it comes to inheritance, the default config of the parent class is automatically, recursively merged with
23601 * the child's default config. The same applies for mixins.
23602 */\r
23603 ExtClass.registerPreprocessor('config', function(Class, data) {\r
23604 // Need to copy to the prototype here because that happens after preprocessors\r
23605 if (data.hasOwnProperty('$configPrefixed')) {\r
23606 Class.prototype.$configPrefixed = data.$configPrefixed;\r
23607 }\r
23608 Class.addConfig(data.config);\r
23609 // We need to remove this or it will be applied by addMembers and smash the\r
23610 // "config" placed on the prototype by Configurator (which includes *all* configs\r
23611 // such as cachedConfigs).\r
23612 delete data.config;\r
23613 });\r
23614 /**
23615 * @cfg {Object} cachedConfig
23616 *
23617 * This configuration works in a very similar manner to the {@link #config} option.
23618 * The difference is that the configurations are only ever processed when the first instance
23619 * of that class is created. The processed value is then stored on the class prototype and
23620 * will not be processed on subsequent instances of the class. Getters/setters will be generated
23621 * in exactly the same way as {@link #config}.
23622 *
23623 * This option is useful for expensive objects that can be shared across class instances.
23624 * The class itself ensures that the creation only occurs once.
23625 */\r
23626 ExtClass.registerPreprocessor('cachedConfig', function(Class, data) {\r
23627 // Need to copy to the prototype here because that happens after preprocessors\r
23628 if (data.hasOwnProperty('$configPrefixed')) {\r
23629 Class.prototype.$configPrefixed = data.$configPrefixed;\r
23630 }\r
23631 Class.addCachedConfig(data.cachedConfig);\r
23632 // Remove this so it won't be placed on the prototype.\r
23633 delete data.cachedConfig;\r
23634 });\r
23635 /**
23636 * @cfg {String[]/Object} mixins
23637 * List of classes to mix into this class. For example:
23638 *
23639 * Ext.define('CanSing', {
23640 * sing: function() {
23641 * alert("For he's a jolly good fellow...")
23642 * }
23643 * });
23644 *
23645 * Ext.define('Musician', {
23646 * mixins: ['CanSing']
23647 * })
23648 *
23649 * In this case the Musician class will get a `sing` method from CanSing mixin.
23650 *
23651 * But what if the Musician already has a `sing` method? Or you want to mix
23652 * in two classes, both of which define `sing`? In such a cases it's good
23653 * to define mixins as an object, where you assign a name to each mixin:
23654 *
23655 * Ext.define('Musician', {
23656 * mixins: {
23657 * canSing: 'CanSing'
23658 * },
23659 *
23660 * sing: function() {
23661 * // delegate singing operation to mixin
23662 * this.mixins.canSing.sing.call(this);
23663 * }
23664 * })
23665 *
23666 * In this case the `sing` method of Musician will overwrite the
23667 * mixed in `sing` method. But you can access the original mixed in method
23668 * through special `mixins` property.
23669 */\r
23670 ExtClass.registerPreprocessor('mixins', function(Class, data, hooks) {\r
23671 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#mixinsPreprocessor', arguments);\r
23672 var mixins = data.mixins,\r
23673 onCreated = hooks.onCreated;\r
23674 delete data.mixins;\r
23675 hooks.onCreated = function() {\r
23676 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#mixinsPreprocessor#beforeCreated', arguments);\r
23677 // Put back the original onCreated before processing mixins. This allows a\r
23678 // mixin to hook onCreated by access Class._classHooks.\r
23679 hooks.onCreated = onCreated;\r
23680 Class.mixin(mixins);\r
23681 // We must go back to hooks.onCreated here because it may have changed during\r
23682 // calls to onClassMixedIn.\r
23683 return hooks.onCreated.apply(this, arguments);\r
23684 };\r
23685 });\r
23686 // Backwards compatible\r
23687 Ext.extend = function(Class, Parent, members) {\r
23688 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#extend-backwards-compatible', arguments);\r
23689 if (arguments.length === 2 && Ext.isObject(Parent)) {\r
23690 members = Parent;\r
23691 Parent = Class;\r
23692 Class = null;\r
23693 }\r
23694 var cls;\r
23695 if (!Parent) {\r
23696 throw new Error("[Ext.extend] Attempting to extend from a class which has not been loaded on the page.");\r
23697 }\r
23698 members.extend = Parent;\r
23699 members.preprocessors = [\r
23700 'extend',\r
23701 'statics',\r
23702 'inheritableStatics',\r
23703 'mixins',\r
23704 'platformConfig',\r
23705 'config'\r
23706 ];\r
23707 if (Class) {\r
23708 cls = new ExtClass(Class, members);\r
23709 // The 'constructor' is given as 'Class' but also needs to be on prototype\r
23710 cls.prototype.constructor = Class;\r
23711 } else {\r
23712 cls = new ExtClass(members);\r
23713 }\r
23714 cls.prototype.override = function(o) {\r
23715 for (var m in o) {\r
23716 if (o.hasOwnProperty(m)) {\r
23717 this[m] = o[m];\r
23718 }\r
23719 }\r
23720 };\r
23721 return cls;\r
23722 };\r
23723}());\r
23724/**
23725 * This object contains properties that describe the current device or platform. These
23726 * values can be used in `{@link Ext.Class#platformConfig platformConfig}` as well as
23727 * `{@link Ext.mixin.Responsive#responsiveConfig responsiveConfig}` statements.
23728 *
23729 * This object can be modified to include tags that are useful for the application. To
23730 * add custom properties, it is advisable to use a sub-object. For example:
23731 *
23732 * Ext.platformTags.app = {
23733 * mobile: true
23734 * };
23735 *
23736 * @property {Object} platformTags
23737 * @property {Boolean} platformTags.phone
23738 * @property {Boolean} platformTags.tablet
23739 * @property {Boolean} platformTags.desktop
23740 * @property {Boolean} platformTags.touch Indicates touch inputs are available.
23741 * @property {Boolean} platformTags.safari
23742 * @property {Boolean} platformTags.chrome
23743 * @property {Boolean} platformTags.windows
23744 * @property {Boolean} platformTags.firefox
23745 * @property {Boolean} platformTags.ios True for iPad, iPhone and iPod.
23746 * @property {Boolean} platformTags.android
23747 * @property {Boolean} platformTags.blackberry
23748 * @property {Boolean} platformTags.tizen
23749 * @member Ext
23750 */\r
23751\r
23752// @tag class\r
23753/**
23754 * @class Ext.Inventory
23755 * @private
23756 */\r
23757Ext.Inventory = function() {\r
23758 // @define Ext.Script\r
23759 // @define Ext.Inventory\r
23760 // @require Ext.Function\r
23761 var me = this;\r
23762 me.names = [];\r
23763 me.paths = {};\r
23764 me.alternateToName = {};\r
23765 me.aliasToName = {};\r
23766 me.nameToAliases = {};\r
23767 me.nameToAlternates = {};\r
23768};\r
23769Ext.Inventory.prototype = {\r
23770 _array1: [\r
23771 0\r
23772 ],\r
23773 prefixes: null,\r
23774 dotRe: /\./g,\r
23775 wildcardRe: /\*/g,\r
23776 addAlias: function(className, alias, update) {\r
23777 return this.addMapping(className, alias, this.aliasToName, this.nameToAliases, update);\r
23778 },\r
23779 addAlternate: function(className, alternate) {\r
23780 return this.addMapping(className, alternate, this.alternateToName, this.nameToAlternates);\r
23781 },\r
23782 addMapping: function(className, alternate, toName, nameTo, update) {\r
23783 var name = className.$className || className,\r
23784 mappings = name,\r
23785 array = this._array1,\r
23786 a, aliases, cls, i, length, nameMapping;\r
23787 if (Ext.isString(name)) {\r
23788 mappings = {};\r
23789 mappings[name] = alternate;\r
23790 }\r
23791 for (cls in mappings) {\r
23792 aliases = mappings[cls];\r
23793 if (Ext.isString(aliases)) {\r
23794 array[0] = aliases;\r
23795 aliases = array;\r
23796 }\r
23797 length = aliases.length;\r
23798 nameMapping = nameTo[cls] || (nameTo[cls] = []);\r
23799 for (i = 0; i < length; ++i) {\r
23800 if (!(a = aliases[i])) {\r
23801 \r
23802 continue;\r
23803 }\r
23804 if (toName[a] !== cls) {\r
23805 if (!update && toName[a]) {\r
23806 Ext.log.warn("Overriding existing mapping: '" + a + "' From '" + toName[a] + "' to '" + cls + "'. Is this intentional?");\r
23807 }\r
23808 toName[a] = cls;\r
23809 nameMapping.push(a);\r
23810 }\r
23811 }\r
23812 }\r
23813 },\r
23814 /**
23815 * Get the aliases of a class by the class name
23816 *
23817 * @param {String} name
23818 * @return {Array} aliases
23819 */\r
23820 getAliasesByName: function(name) {\r
23821 return this.nameToAliases[name] || null;\r
23822 },\r
23823 getAlternatesByName: function(name) {\r
23824 return this.nameToAlternates[name] || null;\r
23825 },\r
23826 /**
23827 * Get the name of a class by its alias.
23828 *
23829 * @param {String} alias
23830 * @return {String} className
23831 */\r
23832 getNameByAlias: function(alias) {\r
23833 return this.aliasToName[alias] || '';\r
23834 },\r
23835 /**
23836 * Get the name of a class by its alternate name.
23837 *
23838 * @param {String} alternate
23839 * @return {String} className
23840 */\r
23841 getNameByAlternate: function(alternate) {\r
23842 return this.alternateToName[alternate] || '';\r
23843 },\r
23844 /**
23845 * Converts a string expression to an array of matching class names. An expression can
23846 * either refers to class aliases or class names. Expressions support wildcards:
23847 *
23848 * // returns ['Ext.window.Window']
23849 * var window = Ext.ClassManager.getNamesByExpression('widget.window');
23850 *
23851 * // returns ['widget.panel', 'widget.window', ...]
23852 * var allWidgets = Ext.ClassManager.getNamesByExpression('widget.*');
23853 *
23854 * // returns ['Ext.data.Store', 'Ext.data.ArrayProxy', ...]
23855 * var allData = Ext.ClassManager.getNamesByExpression('Ext.data.*');
23856 *
23857 * @param {String/String[]} expression
23858 * @param {Object} [exclude=null] An object keyed by class name containing classes to
23859 * exclude from the returned classes. This must be provided if `accumulate` is set to
23860 * `true`.
23861 * @param {Boolean} [accumulate=false] Pass `true` to add matching classes to the
23862 * specified `exclude` object.
23863 * @return {String[]} An array of class names.
23864 */\r
23865 getNamesByExpression: function(expression, exclude, accumulate) {\r
23866 var me = this,\r
23867 aliasToName = me.aliasToName,\r
23868 alternateToName = me.alternateToName,\r
23869 nameToAliases = me.nameToAliases,\r
23870 nameToAlternates = me.nameToAlternates,\r
23871 map = accumulate ? exclude : {},\r
23872 names = [],\r
23873 expressions = Ext.isString(expression) ? [\r
23874 expression\r
23875 ] : expression,\r
23876 length = expressions.length,\r
23877 wildcardRe = me.wildcardRe,\r
23878 expr, i, list, match, n, name, regex;\r
23879 for (i = 0; i < length; ++i) {\r
23880 if ((expr = expressions[i]).indexOf('*') < 0) {\r
23881 // No wildcard\r
23882 if (!(name = aliasToName[expr])) {\r
23883 if (!(name = alternateToName[expr])) {\r
23884 name = expr;\r
23885 }\r
23886 }\r
23887 if (!(name in map) && !(exclude && (name in exclude))) {\r
23888 map[name] = 1;\r
23889 names.push(name);\r
23890 }\r
23891 } else {\r
23892 regex = new RegExp('^' + expr.replace(wildcardRe, '(.*?)') + '$');\r
23893 for (name in nameToAliases) {\r
23894 if (!(name in map) && !(exclude && (name in exclude))) {\r
23895 if (!(match = regex.test(name))) {\r
23896 n = (list = nameToAliases[name]).length;\r
23897 while (!match && n-- > 0) {\r
23898 match = regex.test(list[n]);\r
23899 }\r
23900 list = nameToAlternates[name];\r
23901 if (list && !match) {\r
23902 n = list.length;\r
23903 while (!match && n-- > 0) {\r
23904 match = regex.test(list[n]);\r
23905 }\r
23906 }\r
23907 }\r
23908 if (match) {\r
23909 map[name] = 1;\r
23910 names.push(name);\r
23911 }\r
23912 }\r
23913 }\r
23914 }\r
23915 }\r
23916 return names;\r
23917 },\r
23918 getPath: function(className) {\r
23919 var me = this,\r
23920 paths = me.paths,\r
23921 ret = '',\r
23922 prefix;\r
23923 if (className in paths) {\r
23924 ret = paths[className];\r
23925 } else {\r
23926 prefix = me.getPrefix(className);\r
23927 if (prefix) {\r
23928 className = className.substring(prefix.length + 1);\r
23929 ret = paths[prefix];\r
23930 if (ret) {\r
23931 ret += '/';\r
23932 }\r
23933 }\r
23934 ret += className.replace(me.dotRe, '/') + '.js';\r
23935 }\r
23936 return ret;\r
23937 },\r
23938 getPrefix: function(className) {\r
23939 if (className in this.paths) {\r
23940 return className;\r
23941 }\r
23942 var prefixes = this.getPrefixes(),\r
23943 i = prefixes.length,\r
23944 length, prefix;\r
23945 // Walk the prefixes backwards so we consider the longest ones first.\r
23946 while (i-- > 0) {\r
23947 length = (prefix = prefixes[i]).length;\r
23948 if (length < className.length && className.charAt(length) === '.' && prefix === className.substring(0, length)) {\r
23949 return prefix;\r
23950 }\r
23951 }\r
23952 return '';\r
23953 },\r
23954 getPrefixes: function() {\r
23955 var me = this,\r
23956 prefixes = me.prefixes;\r
23957 if (!prefixes) {\r
23958 me.prefixes = prefixes = me.names.slice(0);\r
23959 prefixes.sort(me._compareNames);\r
23960 }\r
23961 return prefixes;\r
23962 },\r
23963 removeName: function(name) {\r
23964 var me = this,\r
23965 aliasToName = me.aliasToName,\r
23966 alternateToName = me.alternateToName,\r
23967 nameToAliases = me.nameToAliases,\r
23968 nameToAlternates = me.nameToAlternates,\r
23969 aliases = nameToAliases[name],\r
23970 alternates = nameToAlternates[name],\r
23971 i, a;\r
23972 delete nameToAliases[name];\r
23973 delete nameToAlternates[name];\r
23974 if (aliases) {\r
23975 for (i = aliases.length; i--; ) {\r
23976 // Aliases can be reassigned so if this class is the current mapping of\r
23977 // the alias, remove it. Since there is no chain to restore what was\r
23978 // removed this is not perfect.\r
23979 if (name === (a = aliases[i])) {\r
23980 delete aliasToName[a];\r
23981 }\r
23982 }\r
23983 }\r
23984 if (alternates) {\r
23985 for (i = alternates.length; i--; ) {\r
23986 // Like aliases, alternate class names can also be remapped.\r
23987 if (name === (a = alternates[i])) {\r
23988 delete alternateToName[a];\r
23989 }\r
23990 }\r
23991 }\r
23992 },\r
23993 resolveName: function(name) {\r
23994 var me = this,\r
23995 trueName;\r
23996 // If the name has a registered alias, it is a true className (not an alternate)\r
23997 // so we can stop now.\r
23998 if (!(name in me.nameToAliases)) {\r
23999 // The name is not a known class name, so check to see if it is a known alias:\r
24000 if (!(trueName = me.aliasToName[name])) {\r
24001 // The name does not correspond to a known alias, so check if it is a known\r
24002 // alternateClassName:\r
24003 trueName = me.alternateToName[name];\r
24004 }\r
24005 }\r
24006 return trueName || name;\r
24007 },\r
24008 /**
24009 * This method returns a selector object that produces a selection of classes and
24010 * delivers them to the desired `receiver`.
24011 *
24012 * The returned selector object has the same methods as the given `receiver` object
24013 * but these methods on the selector accept a first argument that expects a pattern
24014 * or array of patterns. The actual method on the `receiver` will be called with an
24015 * array of classes that match these patterns but with any patterns passed to an
24016 * `exclude` call removed.
24017 *
24018 * For example:
24019 *
24020 * var sel = inventory.select({
24021 * require: function (classes) {
24022 * console.log('Classes: ' + classes.join(','));
24023 * }
24024 * });
24025 *
24026 * sel.exclude('Ext.chart.*').exclude('Ext.draw.*').require('*');
24027 *
24028 * // Logs all classes except those in the Ext.chart and Ext.draw namespaces.
24029 *
24030 * @param {Object} receiver
24031 * @param {Object} [scope] Optional scope to use when calling `receiver` methods.
24032 * @return {Object} An object with the same methods as `receiver` plus `exclude`.
24033 */\r
24034 select: function(receiver, scope) {\r
24035 var me = this,\r
24036 excludes = {},\r
24037 ret = {\r
24038 excludes: excludes,\r
24039 exclude: function() {\r
24040 me.getNamesByExpression(arguments, excludes, true);\r
24041 return this;\r
24042 }\r
24043 },\r
24044 name;\r
24045 for (name in receiver) {\r
24046 ret[name] = me.selectMethod(excludes, receiver[name], scope || receiver);\r
24047 }\r
24048 return ret;\r
24049 },\r
24050 selectMethod: function(excludes, fn, scope) {\r
24051 var me = this;\r
24052 return function(include) {\r
24053 var args = Ext.Array.slice(arguments, 1);\r
24054 args.unshift(me.getNamesByExpression(include, excludes));\r
24055 return fn.apply(scope, args);\r
24056 };\r
24057 },\r
24058 /**
24059 * Sets the path of a namespace.
24060 * For Example:
24061 *
24062 * inventory.setPath('Ext', '.');
24063 * inventory.setPath({
24064 * Ext: '.'
24065 * });
24066 *
24067 * @param {String/Object} name The name of a single mapping or an object of mappings.
24068 * @param {String} [path] If `name` is a String, then this is the path for that name.
24069 * Otherwise this parameter is ignored.
24070 * @return {Ext.Inventory} this
24071 * @method
24072 */\r
24073 setPath: Ext.Function.flexSetter(function(name, path) {\r
24074 var me = this;\r
24075 me.paths[name] = path;\r
24076 me.names.push(name);\r
24077 me.prefixes = null;\r
24078 return me;\r
24079 }),\r
24080 _compareNames: function(lhs, rhs) {\r
24081 var cmp = lhs.length - rhs.length;\r
24082 if (!cmp) {\r
24083 cmp = (lhs < rhs) ? -1 : 1;\r
24084 }\r
24085 return cmp;\r
24086 }\r
24087};\r
24088\r
24089// @tag class\r
24090/**
24091 * @class Ext.ClassManager
24092 *
24093 * Ext.ClassManager manages all classes and handles mapping from string class name to
24094 * actual class objects throughout the whole framework. It is not generally accessed directly, rather through
24095 * these convenient shorthands:
24096 *
24097 * - {@link Ext#define Ext.define}
24098 * - {@link Ext#create Ext.create}
24099 * - {@link Ext#widget Ext.widget}
24100 * - {@link Ext#getClass Ext.getClass}
24101 * - {@link Ext#getClassName Ext.getClassName}
24102 *
24103 * # Basic syntax:
24104 *
24105 * Ext.define(className, properties);
24106 *
24107 * in which `properties` is an object represent a collection of properties that apply to the class. See
24108 * {@link Ext.ClassManager#create} for more detailed instructions.
24109 *
24110 * Ext.define('Person', {
24111 * name: 'Unknown',
24112 *
24113 * constructor: function(name) {
24114 * if (name) {
24115 * this.name = name;
24116 * }
24117 * },
24118 *
24119 * eat: function(foodType) {
24120 * alert("I'm eating: " + foodType);
24121 *
24122 * return this;
24123 * }
24124 * });
24125 *
24126 * var aaron = new Person("Aaron");
24127 * aaron.eat("Sandwich"); // alert("I'm eating: Sandwich");
24128 *
24129 * Ext.Class has a powerful set of extensible {@link Ext.Class#registerPreprocessor pre-processors} which takes care of
24130 * everything related to class creation, including but not limited to inheritance, mixins, configuration, statics, etc.
24131 *
24132 * # Inheritance:
24133 *
24134 * Ext.define('Developer', {
24135 * extend: 'Person',
24136 *
24137 * constructor: function(name, isGeek) {
24138 * this.isGeek = isGeek;
24139 *
24140 * // Apply a method from the parent class' prototype
24141 * this.callParent([name]);
24142 * },
24143 *
24144 * code: function(language) {
24145 * alert("I'm coding in: " + language);
24146 *
24147 * this.eat("Bugs");
24148 *
24149 * return this;
24150 * }
24151 * });
24152 *
24153 * var jacky = new Developer("Jacky", true);
24154 * jacky.code("JavaScript"); // alert("I'm coding in: JavaScript");
24155 * // alert("I'm eating: Bugs");
24156 *
24157 * See {@link Ext.Base#callParent} for more details on calling superclass' methods
24158 *
24159 * # Mixins:
24160 *
24161 * Ext.define('CanPlayGuitar', {
24162 * playGuitar: function() {
24163 * alert("F#...G...D...A");
24164 * }
24165 * });
24166 *
24167 * Ext.define('CanComposeSongs', {
24168 * composeSongs: function() { ... }
24169 * });
24170 *
24171 * Ext.define('CanSing', {
24172 * sing: function() {
24173 * alert("For he's a jolly good fellow...")
24174 * }
24175 * });
24176 *
24177 * Ext.define('Musician', {
24178 * extend: 'Person',
24179 *
24180 * mixins: {
24181 * canPlayGuitar: 'CanPlayGuitar',
24182 * canComposeSongs: 'CanComposeSongs',
24183 * canSing: 'CanSing'
24184 * }
24185 * })
24186 *
24187 * Ext.define('CoolPerson', {
24188 * extend: 'Person',
24189 *
24190 * mixins: {
24191 * canPlayGuitar: 'CanPlayGuitar',
24192 * canSing: 'CanSing'
24193 * },
24194 *
24195 * sing: function() {
24196 * alert("Ahem....");
24197 *
24198 * this.mixins.canSing.sing.call(this);
24199 *
24200 * alert("[Playing guitar at the same time...]");
24201 *
24202 * this.playGuitar();
24203 * }
24204 * });
24205 *
24206 * var me = new CoolPerson("Jacky");
24207 *
24208 * me.sing(); // alert("Ahem...");
24209 * // alert("For he's a jolly good fellow...");
24210 * // alert("[Playing guitar at the same time...]");
24211 * // alert("F#...G...D...A");
24212 *
24213 * # Config:
24214 *
24215 * Ext.define('SmartPhone', {
24216 * config: {
24217 * hasTouchScreen: false,
24218 * operatingSystem: 'Other',
24219 * price: 500
24220 * },
24221 *
24222 * isExpensive: false,
24223 *
24224 * constructor: function(config) {
24225 * this.initConfig(config);
24226 * },
24227 *
24228 * applyPrice: function(price) {
24229 * this.isExpensive = (price > 500);
24230 *
24231 * return price;
24232 * },
24233 *
24234 * applyOperatingSystem: function(operatingSystem) {
24235 * if (!(/^(iOS|Android|BlackBerry)$/i).test(operatingSystem)) {
24236 * return 'Other';
24237 * }
24238 *
24239 * return operatingSystem;
24240 * }
24241 * });
24242 *
24243 * var iPhone = new SmartPhone({
24244 * hasTouchScreen: true,
24245 * operatingSystem: 'iOS'
24246 * });
24247 *
24248 * iPhone.getPrice(); // 500;
24249 * iPhone.getOperatingSystem(); // 'iOS'
24250 * iPhone.getHasTouchScreen(); // true;
24251 *
24252 * iPhone.isExpensive; // false;
24253 * iPhone.setPrice(600);
24254 * iPhone.getPrice(); // 600
24255 * iPhone.isExpensive; // true;
24256 *
24257 * iPhone.setOperatingSystem('AlienOS');
24258 * iPhone.getOperatingSystem(); // 'Other'
24259 *
24260 * # Statics:
24261 *
24262 * Ext.define('Computer', {
24263 * statics: {
24264 * factory: function(brand) {
24265 * // 'this' in static methods refer to the class itself
24266 * return new this(brand);
24267 * }
24268 * },
24269 *
24270 * constructor: function() { ... }
24271 * });
24272 *
24273 * var dellComputer = Computer.factory('Dell');
24274 *
24275 * Also see {@link Ext.Base#statics} and {@link Ext.Base#self} for more details on accessing
24276 * static properties within class methods
24277 *
24278 * @singleton
24279 */\r
24280Ext.ClassManager = (function(Class, alias, arraySlice, arrayFrom, global) {\r
24281 // @define Ext.ClassManager\r
24282 // @require Ext.Inventory\r
24283 // @require Ext.Class\r
24284 // @require Ext.Function\r
24285 // @require Ext.Array\r
24286 var makeCtor = Ext.Class.makeCtor,\r
24287 nameLookupStack = [],\r
24288 namespaceCache = {\r
24289 Ext: {\r
24290 name: 'Ext',\r
24291 value: Ext\r
24292 }\r
24293 },\r
24294 // specially added for sandbox (Ext === global.Ext6)\r
24295 /*
24296 'Ext.grid': {
24297 name: 'grid',
24298 parent: namespaceCache['Ext']
24299 },
24300 'Ext.grid.Panel': {
24301 name: 'Panel',
24302 parent: namespaceCache['Ext.grid']
24303 },
24304 ...
24305
24306 Also,
24307 'MyApp': {
24308 name: 'MyApp',
24309 value: MyApp
24310 }
24311 */\r
24312 Manager = Ext.apply(new Ext.Inventory(), {\r
24313 /**
24314 * @property {Object} classes
24315 * All classes which were defined through the ClassManager. Keys are the
24316 * name of the classes and the values are references to the classes.
24317 * @private
24318 */\r
24319 classes: {},\r
24320 classState: {},\r
24321 /*
24322 * 'Ext.foo.Bar': <state enum>
24323 *
24324 * 10 = Ext.define called
24325 * 20 = Ext.define/override called
24326 * 30 = Manager.existCache[<name>] == true for define
24327 * 40 = Manager.existCache[<name>] == true for define/override
24328 * 50 = Manager.isCreated(<name>) == true for define
24329 * 60 = Manager.isCreated(<name>) == true for define/override
24330 *
24331 */\r
24332 /**
24333 * @private
24334 */\r
24335 existCache: {},\r
24336 /** @private */\r
24337 instantiators: [],\r
24338 /**
24339 * Checks if a class has already been created.
24340 *
24341 * @param {String} className
24342 * @return {Boolean} exist
24343 */\r
24344 isCreated: function(className) {\r
24345 if (typeof className !== 'string' || className.length < 1) {\r
24346 throw new Error("[Ext.ClassManager] Invalid classname, must be a string and must not be empty");\r
24347 }\r
24348 if (Manager.classes[className] || Manager.existCache[className]) {\r
24349 return true;\r
24350 }\r
24351 if (!Manager.lookupName(className, false)) {\r
24352 return false;\r
24353 }\r
24354 Manager.triggerCreated(className);\r
24355 return true;\r
24356 },\r
24357 /**
24358 * @private
24359 */\r
24360 createdListeners: [],\r
24361 /**
24362 * @private
24363 */\r
24364 nameCreatedListeners: {},\r
24365 /**
24366 * @private
24367 */\r
24368 existsListeners: [],\r
24369 /**
24370 * @private
24371 */\r
24372 nameExistsListeners: {},\r
24373 /**
24374 * @private
24375 */\r
24376 overrideMap: {},\r
24377 /**
24378 * @private
24379 */\r
24380 triggerCreated: function(className, state) {\r
24381 Manager.existCache[className] = state || 1;\r
24382 Manager.classState[className] += 40;\r
24383 Manager.notify(className, Manager.createdListeners, Manager.nameCreatedListeners);\r
24384 },\r
24385 /**
24386 * @private
24387 */\r
24388 onCreated: function(fn, scope, className) {\r
24389 Manager.addListener(fn, scope, className, Manager.createdListeners, Manager.nameCreatedListeners);\r
24390 },\r
24391 /**
24392 * @private
24393 */\r
24394 notify: function(className, listeners, nameListeners) {\r
24395 var alternateNames = Manager.getAlternatesByName(className),\r
24396 names = [\r
24397 className\r
24398 ],\r
24399 i, ln, j, subLn, listener, name;\r
24400 for (i = 0 , ln = listeners.length; i < ln; i++) {\r
24401 listener = listeners[i];\r
24402 listener.fn.call(listener.scope, className);\r
24403 }\r
24404 while (names) {\r
24405 for (i = 0 , ln = names.length; i < ln; i++) {\r
24406 name = names[i];\r
24407 listeners = nameListeners[name];\r
24408 if (listeners) {\r
24409 for (j = 0 , subLn = listeners.length; j < subLn; j++) {\r
24410 listener = listeners[j];\r
24411 listener.fn.call(listener.scope, name);\r
24412 }\r
24413 delete nameListeners[name];\r
24414 }\r
24415 }\r
24416 names = alternateNames;\r
24417 // for 2nd pass (if needed)\r
24418 alternateNames = null;\r
24419 }\r
24420 },\r
24421 // no 3rd pass\r
24422 /**
24423 * @private
24424 */\r
24425 addListener: function(fn, scope, className, listeners, nameListeners) {\r
24426 if (Ext.isArray(className)) {\r
24427 fn = Ext.Function.createBarrier(className.length, fn, scope);\r
24428 for (i = 0; i < className.length; i++) {\r
24429 this.addListener(fn, null, className[i], listeners, nameListeners);\r
24430 }\r
24431 return;\r
24432 }\r
24433 var i,\r
24434 listener = {\r
24435 fn: fn,\r
24436 scope: scope\r
24437 };\r
24438 if (className) {\r
24439 if (this.isCreated(className)) {\r
24440 fn.call(scope, className);\r
24441 return;\r
24442 }\r
24443 if (!nameListeners[className]) {\r
24444 nameListeners[className] = [];\r
24445 }\r
24446 nameListeners[className].push(listener);\r
24447 } else {\r
24448 listeners.push(listener);\r
24449 }\r
24450 },\r
24451 /**
24452 * Supports namespace rewriting.
24453 * @private
24454 */\r
24455 $namespaceCache: namespaceCache,\r
24456 /**
24457 * See `{@link Ext#addRootNamespaces Ext.addRootNamespaces}`.
24458 * @since 6.0.0
24459 * @private
24460 */\r
24461 addRootNamespaces: function(namespaces) {\r
24462 for (var name in namespaces) {\r
24463 namespaceCache[name] = {\r
24464 name: name,\r
24465 value: namespaces[name]\r
24466 };\r
24467 }\r
24468 },\r
24469 /**
24470 * Clears the namespace lookup cache. After application launch, this cache can
24471 * often contain several hundred entries that are unlikely to be needed again.
24472 * These will be rebuilt as needed, so it is harmless to clear this cache even
24473 * if its results will be used again.
24474 * @since 6.0.0
24475 * @private
24476 */\r
24477 clearNamespaceCache: function() {\r
24478 nameLookupStack.length = 0;\r
24479 for (var name in namespaceCache) {\r
24480 if (!namespaceCache[name].value) {\r
24481 delete namespaceCache[name];\r
24482 }\r
24483 }\r
24484 },\r
24485 /**
24486 * Return the namespace cache entry for the given a class name or namespace (e.g.,
24487 * "Ext.grid.Panel").
24488 *
24489 * @param {String} namespace The namespace or class name to lookup.
24490 * @return {Object} The cache entry.
24491 * @return {String} return.name The leaf name ("Panel" for "Ext.grid.Panel").
24492 * @return {Object} return.parent The entry of the parent namespace (i.e., "Ext.grid").
24493 * @return {Object} return.value The namespace object. This is only set for
24494 * top-level namespace entries to support renaming them for sandboxing ("Ext6" vs
24495 * "Ext").
24496 * @since 6.0.0
24497 * @private
24498 */\r
24499 getNamespaceEntry: function(namespace) {\r
24500 if (typeof namespace !== 'string') {\r
24501 return namespace;\r
24502 }\r
24503 // assume we've been given an entry object\r
24504 var entry = namespaceCache[namespace],\r
24505 i;\r
24506 if (!entry) {\r
24507 i = namespace.lastIndexOf('.');\r
24508 if (i < 0) {\r
24509 entry = {\r
24510 name: namespace\r
24511 };\r
24512 } else {\r
24513 entry = {\r
24514 name: namespace.substring(i + 1),\r
24515 parent: Manager.getNamespaceEntry(namespace.substring(0, i))\r
24516 };\r
24517 }\r
24518 namespaceCache[namespace] = entry;\r
24519 }\r
24520 return entry;\r
24521 },\r
24522 /**
24523 * Return the value of the given "dot path" name. This supports remapping (for use
24524 * in sandbox builds) as well as auto-creating of namespaces.
24525 *
24526 * @param {String} namespace The name of the namespace or class.
24527 * @param {Boolean} [autoCreate] Pass `true` to create objects for undefined names.
24528 * @return {Object} The object that is the namespace or class name.
24529 * @since 6.0.0
24530 * @private
24531 */\r
24532 lookupName: function(namespace, autoCreate) {\r
24533 var entry = Manager.getNamespaceEntry(namespace),\r
24534 scope = Ext.global,\r
24535 i = 0,\r
24536 e, parent;\r
24537 // Put entries on the stack in reverse order: [ 'Panel', 'grid', 'Ext' ]\r
24538 for (e = entry; e; e = e.parent) {\r
24539 // since we process only what we add to the array, and that always\r
24540 // starts at index=0, we don't need to clean up the array (that would\r
24541 // just encourage the GC to do something pointless).\r
24542 nameLookupStack[i++] = e;\r
24543 }\r
24544 while (scope && i-- > 0) {\r
24545 // We'll process entries in top-down order ('Ext', 'grid' then 'Panel').\r
24546 e = nameLookupStack[i];\r
24547 parent = scope;\r
24548 scope = e.value || scope[e.name];\r
24549 if (!scope && autoCreate) {\r
24550 parent[e.name] = scope = {};\r
24551 }\r
24552 }\r
24553 return scope;\r
24554 },\r
24555 /**
24556 * Creates a namespace and assign the `value` to the created object.
24557 *
24558 * Ext.ClassManager.setNamespace('MyCompany.pkg.Example', someObject);
24559 *
24560 * alert(MyCompany.pkg.Example === someObject); // alerts true
24561 *
24562 * @param {String} name
24563 * @param {Object} value
24564 */\r
24565 setNamespace: function(namespace, value) {\r
24566 var entry = Manager.getNamespaceEntry(namespace),\r
24567 scope = Ext.global;\r
24568 if (entry.parent) {\r
24569 scope = Manager.lookupName(entry.parent, true);\r
24570 }\r
24571 scope[entry.name] = value;\r
24572 return value;\r
24573 },\r
24574 /**
24575 * Changes the mapping of an `xtype` to map to the specified component class.
24576 * @param {String/Ext.Class} cls The class or class name to which `xtype` is mapped.
24577 * @param {String} xtype The `xtype` to map or redefine as `cls`.
24578 * @since 6.0.1
24579 * @private
24580 */\r
24581 setXType: function(cls, xtype) {\r
24582 var className = cls.$className,\r
24583 C = className ? cls : Manager.get(className = cls),\r
24584 proto = C.prototype,\r
24585 xtypes = proto.xtypes,\r
24586 xtypesChain = proto.xtypesChain,\r
24587 xtypesMap = proto.xtypesMap;\r
24588 if (!proto.hasOwnProperty('xtypes')) {\r
24589 proto.xtypes = xtypes = [];\r
24590 proto.xtypesChain = xtypesChain = xtypesChain ? xtypesChain.slice(0) : [];\r
24591 proto.xtypesMap = xtypesMap = Ext.apply({}, xtypesMap);\r
24592 }\r
24593 Manager.addAlias(className, 'widget.' + xtype, true);\r
24594 xtypes.push(xtype);\r
24595 xtypesChain.push(xtype);\r
24596 xtypesMap[xtype] = true;\r
24597 },\r
24598 //TODO consider updating derived class xtypesChain / xtypesMap\r
24599 /**
24600 * Sets a name reference to a class.
24601 *
24602 * @param {String} name
24603 * @param {Object} value
24604 * @return {Ext.ClassManager} this
24605 */\r
24606 set: function(name, value) {\r
24607 var targetName = Manager.getName(value);\r
24608 Manager.classes[name] = Manager.setNamespace(name, value);\r
24609 if (targetName && targetName !== name) {\r
24610 Manager.addAlternate(targetName, name);\r
24611 }\r
24612 return Manager;\r
24613 },\r
24614 /**
24615 * Retrieve a class by its name.
24616 *
24617 * @param {String} name
24618 * @return {Ext.Class} class
24619 */\r
24620 get: function(name) {\r
24621 return Manager.classes[name] || Manager.lookupName(name, false);\r
24622 },\r
24623 /**
24624 * Adds a batch of class name to alias mappings.
24625 * @param {Object} aliases The set of mappings of the form.
24626 * className : [values...]
24627 */\r
24628 addNameAliasMappings: function(aliases) {\r
24629 Manager.addAlias(aliases);\r
24630 },\r
24631 /**
24632 *
24633 * @param {Object} alternates The set of mappings of the form
24634 * className : [values...]
24635 */\r
24636 addNameAlternateMappings: function(alternates) {\r
24637 Manager.addAlternate(alternates);\r
24638 },\r
24639 /**
24640 * Get a reference to the class by its alias.
24641 *
24642 * @param {String} alias
24643 * @return {Ext.Class} class
24644 */\r
24645 getByAlias: function(alias) {\r
24646 return Manager.get(Manager.getNameByAlias(alias));\r
24647 },\r
24648 /**
24649 * Get a component class name from a config object.
24650 * @param {Object} config The config object.
24651 * @param {String} [aliasPrefix] A prefix to use when getting
24652 * a class name by alias.
24653 * @return {Ext.Class} The class.
24654 *
24655 * @private
24656 */\r
24657 getByConfig: function(config, aliasPrefix) {\r
24658 var xclass = config.xclass,\r
24659 name;\r
24660 if (xclass) {\r
24661 name = xclass;\r
24662 } else {\r
24663 name = config.xtype;\r
24664 if (name) {\r
24665 aliasPrefix = 'widget.';\r
24666 } else {\r
24667 name = config.type;\r
24668 }\r
24669 name = Manager.getNameByAlias(aliasPrefix + name);\r
24670 }\r
24671 return Manager.get(name);\r
24672 },\r
24673 /**
24674 * Get the name of the class by its reference or its instance. This is
24675 * usually invoked by the shorthand {@link Ext#getClassName}.
24676 *
24677 * Ext.ClassManager.getName(Ext.Action); // returns "Ext.Action"
24678 *
24679 * @param {Ext.Class/Object} object
24680 * @return {String} className
24681 */\r
24682 getName: function(object) {\r
24683 return object && object.$className || '';\r
24684 },\r
24685 /**
24686 * Get the class of the provided object; returns null if it's not an instance
24687 * of any class created with Ext.define. This is usually invoked by the
24688 * shorthand {@link Ext#getClass}.
24689 *
24690 * var component = new Ext.Component();
24691 *
24692 * Ext.getClass(component); // returns Ext.Component
24693 *
24694 * @param {Object} object
24695 * @return {Ext.Class} class
24696 */\r
24697 getClass: function(object) {\r
24698 return object && object.self || null;\r
24699 },\r
24700 /**
24701 * Defines a class.
24702 * @deprecated Use {@link Ext#define} instead, as that also supports creating overrides.
24703 * @private
24704 */\r
24705 create: function(className, data, createdFn) {\r
24706 if (className != null && typeof className !== 'string') {\r
24707 throw new Error("[Ext.define] Invalid class name '" + className + "' specified, must be a non-empty string");\r
24708 }\r
24709 var ctor = makeCtor(className);\r
24710 if (typeof data === 'function') {\r
24711 data = data(ctor);\r
24712 }\r
24713 if (className) {\r
24714 if (Manager.classes[className]) {\r
24715 Ext.log.warn("[Ext.define] Duplicate class name '" + className + "' specified, must be a non-empty string");\r
24716 }\r
24717 ctor.name = className;\r
24718 }\r
24719 data.$className = className;\r
24720 return new Class(ctor, data, function() {\r
24721 var postprocessorStack = data.postprocessors || Manager.defaultPostprocessors,\r
24722 registeredPostprocessors = Manager.postprocessors,\r
24723 postprocessors = [],\r
24724 postprocessor, i, ln, j, subLn, postprocessorProperties, postprocessorProperty;\r
24725 delete data.postprocessors;\r
24726 for (i = 0 , ln = postprocessorStack.length; i < ln; i++) {\r
24727 postprocessor = postprocessorStack[i];\r
24728 if (typeof postprocessor === 'string') {\r
24729 postprocessor = registeredPostprocessors[postprocessor];\r
24730 postprocessorProperties = postprocessor.properties;\r
24731 if (postprocessorProperties === true) {\r
24732 postprocessors.push(postprocessor.fn);\r
24733 } else if (postprocessorProperties) {\r
24734 for (j = 0 , subLn = postprocessorProperties.length; j < subLn; j++) {\r
24735 postprocessorProperty = postprocessorProperties[j];\r
24736 if (data.hasOwnProperty(postprocessorProperty)) {\r
24737 postprocessors.push(postprocessor.fn);\r
24738 break;\r
24739 }\r
24740 }\r
24741 }\r
24742 } else {\r
24743 postprocessors.push(postprocessor);\r
24744 }\r
24745 }\r
24746 data.postprocessors = postprocessors;\r
24747 data.createdFn = createdFn;\r
24748 Manager.processCreate(className, this, data);\r
24749 });\r
24750 },\r
24751 processCreate: function(className, cls, clsData) {\r
24752 var me = this,\r
24753 postprocessor = clsData.postprocessors.shift(),\r
24754 createdFn = clsData.createdFn;\r
24755 if (!postprocessor) {\r
24756 Ext.classSystemMonitor && Ext.classSystemMonitor(className, 'Ext.ClassManager#classCreated', arguments);\r
24757 if (className) {\r
24758 me.set(className, cls);\r
24759 }\r
24760 delete cls._classHooks;\r
24761 if (createdFn) {\r
24762 createdFn.call(cls, cls);\r
24763 }\r
24764 if (className) {\r
24765 me.triggerCreated(className);\r
24766 }\r
24767 return;\r
24768 }\r
24769 if (postprocessor.call(me, className, cls, clsData, me.processCreate) !== false) {\r
24770 me.processCreate(className, cls, clsData);\r
24771 }\r
24772 },\r
24773 createOverride: function(className, data, createdFn) {\r
24774 var me = this,\r
24775 overriddenClassName = data.override,\r
24776 requires = data.requires,\r
24777 uses = data.uses,\r
24778 mixins = data.mixins,\r
24779 mixinsIsArray,\r
24780 compat = 1,\r
24781 // default if 'compatibility' is not specified\r
24782 depedenciesLoaded,\r
24783 classReady = function() {\r
24784 var cls, dependencies, i, key, temp;\r
24785 if (!depedenciesLoaded) {\r
24786 dependencies = requires ? requires.slice(0) : [];\r
24787 if (mixins) {\r
24788 if (!(mixinsIsArray = mixins instanceof Array)) {\r
24789 for (key in mixins) {\r
24790 if (Ext.isString(cls = mixins[key])) {\r
24791 dependencies.push(cls);\r
24792 }\r
24793 }\r
24794 } else {\r
24795 for (i = 0 , temp = mixins.length; i < temp; ++i) {\r
24796 if (Ext.isString(cls = mixins[i])) {\r
24797 dependencies.push(cls);\r
24798 }\r
24799 }\r
24800 }\r
24801 }\r
24802 depedenciesLoaded = true;\r
24803 if (dependencies.length) {\r
24804 // Since the override is going to be used (its target class is\r
24805 // now created), we need to fetch the required classes for the\r
24806 // override and call us back once they are loaded:\r
24807 Ext.require(dependencies, classReady);\r
24808 return;\r
24809 }\r
24810 }\r
24811 // else we have no dependencies, so proceed\r
24812 // transform mixin class names into class references, This\r
24813 // loop can handle both the array and object forms of\r
24814 // mixin definitions\r
24815 if (mixinsIsArray) {\r
24816 for (i = 0 , temp = mixins.length; i < temp; ++i) {\r
24817 if (Ext.isString(cls = mixins[i])) {\r
24818 mixins[i] = Ext.ClassManager.get(cls);\r
24819 }\r
24820 }\r
24821 } else if (mixins) {\r
24822 for (key in mixins) {\r
24823 if (Ext.isString(cls = mixins[key])) {\r
24824 mixins[key] = Ext.ClassManager.get(cls);\r
24825 }\r
24826 }\r
24827 }\r
24828 // The target class and the required classes for this override are\r
24829 // ready, so we can apply the override now:\r
24830 cls = me.get(overriddenClassName);\r
24831 // We don't want to apply these:\r
24832 delete data.override;\r
24833 delete data.compatibility;\r
24834 delete data.requires;\r
24835 delete data.uses;\r
24836 Ext.override(cls, data);\r
24837 // This pushes the overriding file itself into Ext.Loader.history\r
24838 // Hence if the target class never exists, the overriding file will\r
24839 // never be included in the build.\r
24840 Ext.Loader.history.push(className);\r
24841 if (uses) {\r
24842 // This "hides" from the Cmd auto-dependency scanner since\r
24843 // the reference is circular (Loader requires us).\r
24844 Ext['Loader'].addUsedClasses(uses);\r
24845 }\r
24846 // get these classes too!\r
24847 if (createdFn) {\r
24848 createdFn.call(cls, cls);\r
24849 }\r
24850 };\r
24851 // last but not least!\r
24852 Manager.overrideMap[className] = true;\r
24853 // If specified, parse strings as versions, but otherwise treat as a\r
24854 // boolean (maybe "compatibility: Ext.isIE8" or something).\r
24855 //\r
24856 if ('compatibility' in data && Ext.isString(compat = data.compatibility)) {\r
24857 compat = Ext.checkVersion(compat);\r
24858 }\r
24859 if (compat) {\r
24860 // Override the target class right after it's created\r
24861 me.onCreated(classReady, me, overriddenClassName);\r
24862 }\r
24863 me.triggerCreated(className, 2);\r
24864 return me;\r
24865 },\r
24866 /**
24867 * Instantiate a class by its alias. This is usually invoked by the
24868 * shorthand {@link Ext#createByAlias}.
24869 *
24870 * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class
24871 * has not been defined yet, it will attempt to load the class via synchronous
24872 * loading.
24873 *
24874 * var window = Ext.createByAlias('widget.window', { width: 600, height: 800 });
24875 *
24876 * @param {String} alias
24877 * @param {Object...} args Additional arguments after the alias will be passed to the
24878 * class constructor.
24879 * @return {Object} instance
24880 */\r
24881 instantiateByAlias: function() {\r
24882 var alias = arguments[0],\r
24883 args = arraySlice.call(arguments),\r
24884 className = this.getNameByAlias(alias);\r
24885 if (!className) {\r
24886 throw new Error("[Ext.createByAlias] Unrecognized alias: " + alias);\r
24887 }\r
24888 args[0] = className;\r
24889 return Ext.create.apply(Ext, args);\r
24890 },\r
24891 /**
24892 * Instantiate a class by either full name, alias or alternate name
24893 * @param {String} name
24894 * @param {Mixed} args Additional arguments after the name will be passed to the class' constructor.
24895 * @return {Object} instance
24896 * @deprecated 5.0 Use Ext.create() instead.
24897 */\r
24898 instantiate: function() {\r
24899 Ext.log.warn('Ext.ClassManager.instantiate() is deprecated. Use Ext.create() instead.');\r
24900 return Ext.create.apply(Ext, arguments);\r
24901 },\r
24902 /**
24903 * @private
24904 * @param name
24905 * @param args
24906 */\r
24907 dynInstantiate: function(name, args) {\r
24908 args = arrayFrom(args, true);\r
24909 args.unshift(name);\r
24910 return Ext.create.apply(Ext, args);\r
24911 },\r
24912 /**
24913 * @private
24914 * @param length
24915 */\r
24916 getInstantiator: function(length) {\r
24917 var instantiators = this.instantiators,\r
24918 instantiator, i, args;\r
24919 instantiator = instantiators[length];\r
24920 if (!instantiator) {\r
24921 i = length;\r
24922 args = [];\r
24923 for (i = 0; i < length; i++) {\r
24924 args.push('a[' + i + ']');\r
24925 }\r
24926 instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');\r
24927 instantiator.name = "Ext.create" + length;\r
24928 }\r
24929 return instantiator;\r
24930 },\r
24931 /**
24932 * @private
24933 */\r
24934 postprocessors: {},\r
24935 /**
24936 * @private
24937 */\r
24938 defaultPostprocessors: [],\r
24939 /**
24940 * Register a post-processor function.
24941 *
24942 * @private
24943 * @param {String} name
24944 * @param {Function} postprocessor
24945 */\r
24946 registerPostprocessor: function(name, fn, properties, position, relativeTo) {\r
24947 if (!position) {\r
24948 position = 'last';\r
24949 }\r
24950 if (!properties) {\r
24951 properties = [\r
24952 name\r
24953 ];\r
24954 }\r
24955 this.postprocessors[name] = {\r
24956 name: name,\r
24957 properties: properties || false,\r
24958 fn: fn\r
24959 };\r
24960 this.setDefaultPostprocessorPosition(name, position, relativeTo);\r
24961 return this;\r
24962 },\r
24963 /**
24964 * Set the default post processors array stack which are applied to every class.
24965 *
24966 * @private
24967 * @param {String/Array} postprocessors The name of a registered post processor or an array of registered names.
24968 * @return {Ext.ClassManager} this
24969 */\r
24970 setDefaultPostprocessors: function(postprocessors) {\r
24971 this.defaultPostprocessors = arrayFrom(postprocessors);\r
24972 return this;\r
24973 },\r
24974 /**
24975 * Insert this post-processor at a specific position in the stack, optionally relative to
24976 * any existing post-processor
24977 *
24978 * @private
24979 * @param {String} name The post-processor name. Note that it needs to be registered with
24980 * {@link Ext.ClassManager#registerPostprocessor} before this
24981 * @param {String} offset The insertion position. Four possible values are:
24982 * 'first', 'last', or: 'before', 'after' (relative to the name provided in the third argument)
24983 * @param {String} relativeName
24984 * @return {Ext.ClassManager} this
24985 */\r
24986 setDefaultPostprocessorPosition: function(name, offset, relativeName) {\r
24987 var defaultPostprocessors = this.defaultPostprocessors,\r
24988 index;\r
24989 if (typeof offset === 'string') {\r
24990 if (offset === 'first') {\r
24991 defaultPostprocessors.unshift(name);\r
24992 return this;\r
24993 } else if (offset === 'last') {\r
24994 defaultPostprocessors.push(name);\r
24995 return this;\r
24996 }\r
24997 offset = (offset === 'after') ? 1 : -1;\r
24998 }\r
24999 index = Ext.Array.indexOf(defaultPostprocessors, relativeName);\r
25000 if (index !== -1) {\r
25001 Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);\r
25002 }\r
25003 return this;\r
25004 }\r
25005 });\r
25006 /**
25007 * @cfg xtype
25008 * @member Ext.Class
25009 * @inheritdoc Ext.Component#cfg-xtype
25010 */\r
25011 /**
25012 * @cfg {String} override
25013 * @member Ext.Class
25014 * Overrides members of the specified `target` class.
25015 *
25016 * **NOTE:** the overridden class must have been defined using
25017 * {@link Ext#define Ext.define} in order to use the `override` config.
25018 *
25019 * Methods defined on the overriding class will not automatically call the methods of
25020 * the same name in the ancestor class chain. To call the parent's method of the
25021 * same name you must call {@link Ext.Base#callParent callParent}. To skip the
25022 * method of the overridden class and call its parent you will instead call
25023 * {@link Ext.Base#callSuper callSuper}.
25024 *
25025 * See {@link Ext#define Ext.define} for additional usage examples.
25026 */\r
25027 /**
25028 * @cfg {String/String[]} alias
25029 * @member Ext.Class
25030 * List of short aliases for class names. An alias consists of a namespace and a name
25031 * concatenated by a period as &#60;namespace&#62;.&#60;name&#62;
25032 *
25033 * - **namespace** - The namespace describes what kind of alias this is and must be
25034 * all lowercase.
25035 * - **name** - The name of the alias which allows the lazy-instantiation via the
25036 * alias. The name shouldn't contain any periods.
25037 *
25038 * A list of namespaces and the usages are:
25039 *
25040 * - **feature** - {@link Ext.grid.Panel Grid} features
25041 * - **plugin** - Plugins
25042 * - **store** - {@link Ext.data.Store}
25043 * - **widget** - Components
25044 *
25045 * Most useful for defining xtypes for widgets:
25046 *
25047 * Ext.define('MyApp.CoolPanel', {
25048 * extend: 'Ext.panel.Panel',
25049 * alias: ['widget.coolpanel'],
25050 * title: 'Yeah!'
25051 * });
25052 *
25053 * // Using Ext.create
25054 * Ext.create('widget.coolpanel');
25055 *
25056 * // Using the shorthand for defining widgets by xtype
25057 * Ext.widget('panel', {
25058 * items: [
25059 * {xtype: 'coolpanel', html: 'Foo'},
25060 * {xtype: 'coolpanel', html: 'Bar'}
25061 * ]
25062 * });
25063 */\r
25064 Manager.registerPostprocessor('alias', function(name, cls, data) {\r
25065 Ext.classSystemMonitor && Ext.classSystemMonitor(name, 'Ext.ClassManager#aliasPostProcessor', arguments);\r
25066 var aliases = Ext.Array.from(data.alias),\r
25067 i, ln;\r
25068 for (i = 0 , ln = aliases.length; i < ln; i++) {\r
25069 alias = aliases[i];\r
25070 this.addAlias(cls, alias);\r
25071 }\r
25072 }, [\r
25073 'xtype',\r
25074 'alias'\r
25075 ]);\r
25076 /**
25077 * @cfg {Boolean} singleton
25078 * @member Ext.Class
25079 * When set to true, the class will be instantiated as singleton. For example:
25080 *
25081 * Ext.define('Logger', {
25082 * singleton: true,
25083 * log: function(msg) {
25084 * console.log(msg);
25085 * }
25086 * });
25087 *
25088 * Logger.log('Hello');
25089 */\r
25090 Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {\r
25091 Ext.classSystemMonitor && Ext.classSystemMonitor(name, 'Ext.ClassManager#singletonPostProcessor', arguments);\r
25092 if (data.singleton) {\r
25093 fn.call(this, name, new cls(), data);\r
25094 } else {\r
25095 return true;\r
25096 }\r
25097 return false;\r
25098 });\r
25099 /**
25100 * @cfg {String/String[]} alternateClassName
25101 * @member Ext.Class
25102 * Defines alternate names for this class. For example:
25103 *
25104 * Ext.define('Developer', {
25105 * alternateClassName: ['Coder', 'Hacker'],
25106 * code: function(msg) {
25107 * alert('Typing... ' + msg);
25108 * }
25109 * });
25110 *
25111 * var joe = Ext.create('Developer');
25112 * joe.code('stackoverflow');
25113 *
25114 * var rms = Ext.create('Hacker');
25115 * rms.code('hack hack');
25116 */\r
25117 Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {\r
25118 Ext.classSystemMonitor && Ext.classSystemMonitor(name, 'Ext.ClassManager#alternateClassNamePostprocessor', arguments);\r
25119 var alternates = data.alternateClassName,\r
25120 i, ln, alternate;\r
25121 if (!(alternates instanceof Array)) {\r
25122 alternates = [\r
25123 alternates\r
25124 ];\r
25125 }\r
25126 for (i = 0 , ln = alternates.length; i < ln; i++) {\r
25127 alternate = alternates[i];\r
25128 if (typeof alternate !== 'string') {\r
25129 throw new Error("[Ext.define] Invalid alternate of: '" + alternate + "' for class: '" + name + "'; must be a valid string");\r
25130 }\r
25131 this.set(alternate, cls);\r
25132 }\r
25133 });\r
25134 /**
25135 * @cfg {Object} debugHooks
25136 * A collection of diagnostic methods to decorate the real methods of the class. These
25137 * methods are applied as an `override` if this class has debug enabled as defined by
25138 * `Ext.isDebugEnabled`.
25139 *
25140 * These will be automatically removed by the Sencha Cmd compiler for production builds.
25141 *
25142 * Example usage:
25143 *
25144 * Ext.define('Foo.bar.Class', {
25145 * foo: function (a, b, c) {
25146 * ...
25147 * },
25148 *
25149 * bar: function (a, b) {
25150 * ...
25151 * return 42;
25152 * },
25153 *
25154 * debugHooks: {
25155 * foo: function (a, b, c) {
25156 * // check arguments...
25157 * return this.callParent(arguments);
25158 * }
25159 * }
25160 * });
25161 *
25162 * If you specify a `$enabled` property in the `debugHooks` object that will be used
25163 * as the default enabled state for the hooks. If the `{@link Ext#manifest}` contains
25164 * a `debug` object of if `{@link Ext#debugConfig}` is specified, the `$enabled` flag
25165 * will override its "*" value.
25166 */\r
25167 Manager.registerPostprocessor('debugHooks', function(name, Class, data) {\r
25168 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#debugHooks', arguments);\r
25169 if (Ext.isDebugEnabled(Class.$className, data.debugHooks.$enabled)) {\r
25170 delete data.debugHooks.$enabled;\r
25171 Ext.override(Class, data.debugHooks);\r
25172 }\r
25173 // may already have an instance here in the case of singleton\r
25174 var target = Class.isInstance ? Class.self : Class;\r
25175 delete target.prototype.debugHooks;\r
25176 });\r
25177 /**
25178 * @cfg {Object} deprecated
25179 * The object given has properties that describe the versions at which the deprecations
25180 * apply.
25181 *
25182 * The purpose of the `deprecated` declaration is to enable development mode to give
25183 * suitable error messages when deprecated methods or properties are used. Methods can
25184 * always be injected to provide this feedback, but properties can only be handled on
25185 * some browsers (those that support `Object.defineProperty`).
25186 *
25187 * In some cases, deprecated methods can be restored to their previous behavior or
25188 * added back if they have been removed.
25189 *
25190 * The structure of a `deprecated` declaration is this:
25191 *
25192 * Ext.define('Foo.bar.Class', {
25193 * ...
25194 *
25195 * deprecated: {
25196 * // Optional package name - default is the framework (ext or touch)
25197 * name: 'foobar',
25198 *
25199 * '5.0': {
25200 * methods: {
25201 * // Throws: '"removedMethod" is deprecated.'
25202 * removedMethod: null,
25203 *
25204 * // Throws: '"oldMethod" is deprecated. Please use "newMethod" instead.'
25205 * oldMethod: 'newMethod',
25206 *
25207 * // When this block is enabled, this method is applied as an
25208 * // override. Otherwise you get same as "removeMethod".
25209 * method: function () {
25210 * // Do what v5 "method" did. If "method" exists in newer
25211 * // versions callParent can call it. If 5.1 has "method"
25212 * // then it would be next in line, otherwise 5.2 and last
25213 * // would be the current class.
25214 * },
25215 *
25216 * moreHelpful: {
25217 * message: 'Something helpful to do instead.',
25218 * fn: function () {
25219 * // The v5 "moreHelpful" method to use when enabled.
25220 * }
25221 * }
25222 * },
25223 * properties: {
25224 * // Throws: '"removedProp" is deprecated.'
25225 * removedProp: null,
25226 *
25227 * // Throws: '"oldProp" is deprecated. Please use "newProp" instead.'
25228 * oldProp: 'newProp',
25229 *
25230 * helpful: {
25231 * message: 'Something helpful message about what to do.'
25232 * }
25233 * ...
25234 * },
25235 * statics: {
25236 * methods: {
25237 * ...
25238 * },
25239 * properties: {
25240 * ...
25241 * },
25242 * }
25243 * },
25244 *
25245 * '5.1': {
25246 * ...
25247 * },
25248 *
25249 * '5.2': {
25250 * ...
25251 * }
25252 * }
25253 * });
25254 *
25255 * The primary content of `deprecated` are the version number keys. These indicate
25256 * a version number where methods or properties were deprecated. These versions are
25257 * compared to the version reported by `Ext.getCompatVersion` to determine the action
25258 * to take for each "block".
25259 *
25260 * When the compatibility version is set to a value less than a version number key,
25261 * that block is said to be "enabled". For example, if a method was deprecated in
25262 * version 5.0 but the desired compatibility level is 4.2 then the block is used to
25263 * patch methods and (to some degree) restore pre-5.0 compatibility.
25264 *
25265 * When multiple active blocks have the same method name, each method is applied as
25266 * an override in reverse order of version. In the above example, if a method appears
25267 * in the "5.0", "5.1" and "5.2" blocks then the "5.2" method is applied as an override
25268 * first, followed by the "5.1" method and finally the "5.0" method. This means that
25269 * the `callParent` from the "5.0" method calls the "5.1" method which calls the
25270 * "5.2" method which can (if applicable) call the current version.
25271 */\r
25272 Manager.registerPostprocessor('deprecated', function(name, Class, data) {\r
25273 Ext.classSystemMonitor && Ext.classSystemMonitor(Class, 'Ext.Class#deprecated', arguments);\r
25274 // may already have an instance here in the case of singleton\r
25275 var target = Class.isInstance ? Class.self : Class;\r
25276 target.addDeprecations(data.deprecated);\r
25277 delete target.prototype.deprecated;\r
25278 });\r
25279 Ext.apply(Ext, {\r
25280 /**
25281 * Instantiate a class by either full name, alias or alternate name.
25282 *
25283 * If {@link Ext.Loader} is {@link Ext.Loader#setConfig enabled} and the class has
25284 * not been defined yet, it will attempt to load the class via synchronous loading.
25285 *
25286 * For example, all these three lines return the same result:
25287 *
25288 * // xtype
25289 * var window = Ext.create({
25290 * xtype: 'window',
25291 * width: 600,
25292 * height: 800,
25293 * ...
25294 * });
25295 *
25296 * // alias
25297 * var window = Ext.create('widget.window', {
25298 * width: 600,
25299 * height: 800,
25300 * ...
25301 * });
25302 *
25303 * // alternate name
25304 * var window = Ext.create('Ext.Window', {
25305 * width: 600,
25306 * height: 800,
25307 * ...
25308 * });
25309 *
25310 * // full class name
25311 * var window = Ext.create('Ext.window.Window', {
25312 * width: 600,
25313 * height: 800,
25314 * ...
25315 * });
25316 *
25317 * // single object with xclass property:
25318 * var window = Ext.create({
25319 * xclass: 'Ext.window.Window', // any valid value for 'name' (above)
25320 * width: 600,
25321 * height: 800,
25322 * ...
25323 * });
25324 *
25325 * @param {String} [name] The class name or alias. Can be specified as `xclass`
25326 * property if only one object parameter is specified.
25327 * @param {Object...} [args] Additional arguments after the name will be passed to
25328 * the class' constructor.
25329 * @return {Object} instance
25330 * @member Ext
25331 * @method create
25332 */\r
25333 create: function() {\r
25334 var name = arguments[0],\r
25335 nameType = typeof name,\r
25336 args = arraySlice.call(arguments, 1),\r
25337 cls;\r
25338 if (nameType === 'function') {\r
25339 cls = name;\r
25340 } else {\r
25341 if (nameType !== 'string' && args.length === 0) {\r
25342 args = [\r
25343 name\r
25344 ];\r
25345 if (!(name = name.xclass)) {\r
25346 name = args[0].xtype;\r
25347 if (name) {\r
25348 name = 'widget.' + name;\r
25349 }\r
25350 }\r
25351 }\r
25352 if (typeof name !== 'string' || name.length < 1) {\r
25353 throw new Error("[Ext.create] Invalid class name or alias '" + name + "' specified, must be a non-empty string");\r
25354 }\r
25355 name = Manager.resolveName(name);\r
25356 cls = Manager.get(name);\r
25357 }\r
25358 // Still not existing at this point, try to load it via synchronous mode as the last resort\r
25359 if (!cls) {\r
25360 Ext.log.warn("[Ext.Loader] Synchronously loading '" + name + "'; consider adding " + "Ext.require('" + name + "') above Ext.onReady");\r
25361 Ext.syncRequire(name);\r
25362 cls = Manager.get(name);\r
25363 }\r
25364 if (!cls) {\r
25365 throw new Error("[Ext.create] Unrecognized class name / alias: " + name);\r
25366 }\r
25367 if (typeof cls !== 'function') {\r
25368 throw new Error("[Ext.create] Singleton '" + name + "' cannot be instantiated.");\r
25369 }\r
25370 return Manager.getInstantiator(args.length)(cls, args);\r
25371 },\r
25372 /**
25373 * Convenient shorthand to create a widget by its xtype or a config object.
25374 *
25375 * var button = Ext.widget('button'); // Equivalent to Ext.create('widget.button');
25376 *
25377 * var panel = Ext.widget('panel', { // Equivalent to Ext.create('widget.panel')
25378 * title: 'Panel'
25379 * });
25380 *
25381 * var grid = Ext.widget({
25382 * xtype: 'grid',
25383 * ...
25384 * });
25385 *
25386 * If a {@link Ext.Component component} instance is passed, it is simply returned.
25387 *
25388 * @member Ext
25389 * @param {String} [name] The xtype of the widget to create.
25390 * @param {Object} [config] The configuration object for the widget constructor.
25391 * @return {Object} The widget instance
25392 */\r
25393 widget: function(name, config) {\r
25394 // forms:\r
25395 // 1: (xtype)\r
25396 // 2: (xtype, config)\r
25397 // 3: (config)\r
25398 // 4: (xtype, component)\r
25399 // 5: (component)\r
25400 // \r
25401 var xtype = name,\r
25402 alias, className, T;\r
25403 if (typeof xtype !== 'string') {\r
25404 // if (form 3 or 5)\r
25405 // first arg is config or component\r
25406 config = name;\r
25407 // arguments[0]\r
25408 xtype = config.xtype;\r
25409 className = config.xclass;\r
25410 } else {\r
25411 config = config || {};\r
25412 }\r
25413 if (config.isComponent) {\r
25414 return config;\r
25415 }\r
25416 if (!className) {\r
25417 alias = 'widget.' + xtype;\r
25418 className = Manager.getNameByAlias(alias);\r
25419 }\r
25420 // this is needed to support demand loading of the class\r
25421 if (className) {\r
25422 T = Manager.get(className);\r
25423 }\r
25424 if (!T) {\r
25425 return Ext.create(className || alias, config);\r
25426 }\r
25427 return new T(config);\r
25428 },\r
25429 /**
25430 * @inheritdoc Ext.ClassManager#instantiateByAlias
25431 * @member Ext
25432 * @method createByAlias
25433 */\r
25434 createByAlias: alias(Manager, 'instantiateByAlias'),\r
25435 /**
25436 * Defines a class or override. A basic class is defined like this:
25437 *
25438 * Ext.define('My.awesome.Class', {
25439 * someProperty: 'something',
25440 *
25441 * someMethod: function(s) {
25442 * alert(s + this.someProperty);
25443 * }
25444 *
25445 * ...
25446 * });
25447 *
25448 * var obj = new My.awesome.Class();
25449 *
25450 * obj.someMethod('Say '); // alerts 'Say something'
25451 *
25452 * To create an anonymous class, pass `null` for the `className`:
25453 *
25454 * Ext.define(null, {
25455 * constructor: function () {
25456 * // ...
25457 * }
25458 * });
25459 *
25460 * In some cases, it is helpful to create a nested scope to contain some private
25461 * properties. The best way to do this is to pass a function instead of an object
25462 * as the second parameter. This function will be called to produce the class
25463 * body:
25464 *
25465 * Ext.define('MyApp.foo.Bar', function () {
25466 * var id = 0;
25467 *
25468 * return {
25469 * nextId: function () {
25470 * return ++id;
25471 * }
25472 * };
25473 * });
25474 *
25475 * _Note_ that when using override, the above syntax will not override successfully, because
25476 * the passed function would need to be executed first to determine whether or not the result
25477 * is an override or defining a new object. As such, an alternative syntax that immediately
25478 * invokes the function can be used:
25479 *
25480 * Ext.define('MyApp.override.BaseOverride', function () {
25481 * var counter = 0;
25482 *
25483 * return {
25484 * override: 'Ext.Component',
25485 * logId: function () {
25486 * console.log(++counter, this.id);
25487 * }
25488 * };
25489 * }());
25490 *
25491 *
25492 * When using this form of `Ext.define`, the function is passed a reference to its
25493 * class. This can be used as an efficient way to access any static properties you
25494 * may have:
25495 *
25496 * Ext.define('MyApp.foo.Bar', function (Bar) {
25497 * return {
25498 * statics: {
25499 * staticMethod: function () {
25500 * // ...
25501 * }
25502 * },
25503 *
25504 * method: function () {
25505 * return Bar.staticMethod();
25506 * }
25507 * };
25508 * });
25509 *
25510 * To define an override, include the `override` property. The content of an
25511 * override is aggregated with the specified class in order to extend or modify
25512 * that class. This can be as simple as setting default property values or it can
25513 * extend and/or replace methods. This can also extend the statics of the class.
25514 *
25515 * One use for an override is to break a large class into manageable pieces.
25516 *
25517 * // File: /src/app/Panel.js
25518 *
25519 * Ext.define('My.app.Panel', {
25520 * extend: 'Ext.panel.Panel',
25521 * requires: [
25522 * 'My.app.PanelPart2',
25523 * 'My.app.PanelPart3'
25524 * ]
25525 *
25526 * constructor: function (config) {
25527 * this.callParent(arguments); // calls Ext.panel.Panel's constructor
25528 * //...
25529 * },
25530 *
25531 * statics: {
25532 * method: function () {
25533 * return 'abc';
25534 * }
25535 * }
25536 * });
25537 *
25538 * // File: /src/app/PanelPart2.js
25539 * Ext.define('My.app.PanelPart2', {
25540 * override: 'My.app.Panel',
25541 *
25542 * constructor: function (config) {
25543 * this.callParent(arguments); // calls My.app.Panel's constructor
25544 * //...
25545 * }
25546 * });
25547 *
25548 * Another use of overrides is to provide optional parts of classes that can be
25549 * independently required. In this case, the class may even be unaware of the
25550 * override altogether.
25551 *
25552 * Ext.define('My.ux.CoolTip', {
25553 * override: 'Ext.tip.ToolTip',
25554 *
25555 * constructor: function (config) {
25556 * this.callParent(arguments); // calls Ext.tip.ToolTip's constructor
25557 * //...
25558 * }
25559 * });
25560 *
25561 * The above override can now be required as normal.
25562 *
25563 * Ext.define('My.app.App', {
25564 * requires: [
25565 * 'My.ux.CoolTip'
25566 * ]
25567 * });
25568 *
25569 * Overrides can also contain statics, inheritableStatics, or privates:
25570 *
25571 * Ext.define('My.app.BarMod', {
25572 * override: 'Ext.foo.Bar',
25573 *
25574 * statics: {
25575 * method: function (x) {
25576 * return this.callParent([x * 2]); // call Ext.foo.Bar.method
25577 * }
25578 * }
25579 * });
25580 *
25581 * Starting in version 4.2.2, overrides can declare their `compatibility` based
25582 * on the framework version or on versions of other packages. For details on the
25583 * syntax and options for these checks, see `Ext.checkVersion`.
25584 *
25585 * The simplest use case is to test framework version for compatibility:
25586 *
25587 * Ext.define('App.overrides.grid.Panel', {
25588 * override: 'Ext.grid.Panel',
25589 *
25590 * compatibility: '4.2.2', // only if framework version is 4.2.2
25591 *
25592 * //...
25593 * });
25594 *
25595 * An array is treated as an OR, so if any specs match, the override is
25596 * compatible.
25597 *
25598 * Ext.define('App.overrides.some.Thing', {
25599 * override: 'Foo.some.Thing',
25600 *
25601 * compatibility: [
25602 * '4.2.2',
25603 * 'foo@1.0.1-1.0.2'
25604 * ],
25605 *
25606 * //...
25607 * });
25608 *
25609 * To require that all specifications match, an object can be provided:
25610 *
25611 * Ext.define('App.overrides.some.Thing', {
25612 * override: 'Foo.some.Thing',
25613 *
25614 * compatibility: {
25615 * and: [
25616 * '4.2.2',
25617 * 'foo@1.0.1-1.0.2'
25618 * ]
25619 * },
25620 *
25621 * //...
25622 * });
25623 *
25624 * Because the object form is just a recursive check, these can be nested:
25625 *
25626 * Ext.define('App.overrides.some.Thing', {
25627 * override: 'Foo.some.Thing',
25628 *
25629 * compatibility: {
25630 * and: [
25631 * '4.2.2', // exactly version 4.2.2 of the framework *AND*
25632 * {
25633 * // either (or both) of these package specs:
25634 * or: [
25635 * 'foo@1.0.1-1.0.2',
25636 * 'bar@3.0+'
25637 * ]
25638 * }
25639 * ]
25640 * },
25641 *
25642 * //...
25643 * });
25644 *
25645 * IMPORTANT: An override is only included in a build if the class it overrides is
25646 * required. Otherwise, the override, like the target class, is not included. In
25647 * Sencha Cmd v4, the `compatibility` declaration can likewise be used to remove
25648 * incompatible overrides from a build.
25649 *
25650 * @param {String} className The class name to create in string dot-namespaced format, for example:
25651 * 'My.very.awesome.Class', 'FeedViewer.plugin.CoolPager'
25652 * It is highly recommended to follow this simple convention:
25653 * - The root and the class name are 'CamelCased'
25654 * - Everything else is lower-cased
25655 * Pass `null` to create an anonymous class.
25656 * @param {Object} data The key - value pairs of properties to apply to this class. Property names can be of any valid
25657 * strings, except those in the reserved listed below:
25658 *
25659 * - {@link Ext.Class#cfg-alias alias}
25660 * - {@link Ext.Class#cfg-alternateClassName alternateClassName}
25661 * - {@link Ext.Class#cfg-cachedConfig cachedConfig}
25662 * - {@link Ext.Class#cfg-config config}
25663 * - {@link Ext.Class#cfg-extend extend}
25664 * - {@link Ext.Class#cfg-inheritableStatics inheritableStatics}
25665 * - {@link Ext.Class#cfg-mixins mixins}
25666 * - {@link Ext.Class#cfg-override override}
25667 * - {@link Ext.Class#cfg-platformConfig platformConfig}
25668 * - {@link Ext.Class#cfg-privates privates}
25669 * - {@link Ext.Class#cfg-requires requires}
25670 * - `self`
25671 * - {@link Ext.Class#cfg-singleton singleton}
25672 * - {@link Ext.Class#cfg-statics statics}
25673 * - {@link Ext.Class#cfg-uses uses}
25674 * - {@link Ext.Class#cfg-xtype xtype} (for {@link Ext.Component Components} only)
25675 *
25676 * @param {Function} [createdFn] Callback to execute after the class is created, the execution scope of which
25677 * (`this`) will be the newly created class itself.
25678 * @return {Ext.Base}
25679 * @member Ext
25680 */\r
25681 define: function(className, data, createdFn) {\r
25682 Ext.classSystemMonitor && Ext.classSystemMonitor(className, 'ClassManager#define', arguments);\r
25683 if (data.override) {\r
25684 Manager.classState[className] = 20;\r
25685 return Manager.createOverride.apply(Manager, arguments);\r
25686 }\r
25687 Manager.classState[className] = 10;\r
25688 return Manager.create.apply(Manager, arguments);\r
25689 },\r
25690 /**
25691 * Undefines a class defined using the #define method. Typically used
25692 * for unit testing where setting up and tearing down a class multiple
25693 * times is required. For example:
25694 *
25695 * // define a class
25696 * Ext.define('Foo', {
25697 * ...
25698 * });
25699 *
25700 * // run test
25701 *
25702 * // undefine the class
25703 * Ext.undefine('Foo');
25704 * @param {String} className The class name to undefine in string dot-namespaced format.
25705 * @private
25706 */\r
25707 undefine: function(className) {\r
25708 Ext.classSystemMonitor && Ext.classSystemMonitor(className, 'Ext.ClassManager#undefine', arguments);\r
25709 var classes = Manager.classes;\r
25710 delete classes[className];\r
25711 delete Manager.existCache[className];\r
25712 delete Manager.classState[className];\r
25713 Manager.removeName(className);\r
25714 var entry = Manager.getNamespaceEntry(className),\r
25715 scope = entry.parent ? Manager.lookupName(entry.parent, false) : Ext.global;\r
25716 if (scope) {\r
25717 // Old IE blows up on attempt to delete window property\r
25718 try {\r
25719 delete scope[entry.name];\r
25720 } catch (e) {\r
25721 scope[entry.name] = undefined;\r
25722 }\r
25723 }\r
25724 },\r
25725 /**
25726 * @inheritdoc Ext.ClassManager#getName
25727 * @member Ext
25728 * @method getClassName
25729 */\r
25730 getClassName: alias(Manager, 'getName'),\r
25731 /**
25732 * Returns the displayName property or className or object. When all else fails, returns "Anonymous".
25733 * @param {Object} object
25734 * @return {String}
25735 */\r
25736 getDisplayName: function(object) {\r
25737 if (object) {\r
25738 if (object.displayName) {\r
25739 return object.displayName;\r
25740 }\r
25741 if (object.$name && object.$class) {\r
25742 return Ext.getClassName(object.$class) + '#' + object.$name;\r
25743 }\r
25744 if (object.$className) {\r
25745 return object.$className;\r
25746 }\r
25747 }\r
25748 return 'Anonymous';\r
25749 },\r
25750 /**
25751 * @inheritdoc Ext.ClassManager#getClass
25752 * @member Ext
25753 * @method getClass
25754 */\r
25755 getClass: alias(Manager, 'getClass'),\r
25756 /**
25757 * Creates namespaces to be used for scoping variables and classes so that they are not global.
25758 * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
25759 *
25760 * Ext.namespace('Company', 'Company.data');
25761 *
25762 * // equivalent and preferable to the above syntax
25763 * Ext.ns('Company.data');
25764 *
25765 * Company.Widget = function() { ... };
25766 *
25767 * Company.data.CustomStore = function(config) { ... };
25768 *
25769 * @param {String...} namespaces
25770 * @return {Object} The (last) namespace object created.
25771 * @member Ext
25772 * @method namespace
25773 */\r
25774 namespace: function() {\r
25775 var root = global,\r
25776 i;\r
25777 for (i = arguments.length; i-- > 0; ) {\r
25778 root = Manager.lookupName(arguments[i], true);\r
25779 }\r
25780 return root;\r
25781 }\r
25782 });\r
25783 /**
25784 * This function registers top-level (root) namespaces. This is needed for "sandbox"
25785 * builds.
25786 *
25787 * Ext.addRootNamespaces({
25788 * MyApp: MyApp,
25789 * Common: Common
25790 * });
25791 *
25792 * In the above example, `MyApp` and `Common` are top-level namespaces that happen
25793 * to also be included in the sandbox closure. Something like this:
25794 *
25795 * (function(Ext) {
25796 *
25797 * Ext.sandboxName = 'Ext6';
25798 * Ext.isSandboxed = true;
25799 * Ext.buildSettings = { baseCSSPrefix: "x6-", scopeResetCSS: true };
25800 *
25801 * var MyApp = MyApp || {};
25802 * Ext.addRootNamespaces({ MyApp: MyApp );
25803 *
25804 * ... normal app.js goes here ...
25805 *
25806 * })(this.Ext6 || (this.Ext6 = {}));
25807 *
25808 * The sandbox wrapper around the normally built `app.js` content has to take care
25809 * of introducing top-level namespaces as well as call this method.
25810 *
25811 * @param {Object} namespaces
25812 * @method addRootNamespaces
25813 * @member Ext
25814 * @since 6.0.0
25815 * @private
25816 */\r
25817 Ext.addRootNamespaces = Manager.addRootNamespaces;\r
25818 /**
25819 * Old name for {@link Ext#widget}.
25820 * @deprecated Use {@link Ext#widget} instead.
25821 * @method createWidget
25822 * @member Ext
25823 * @private
25824 */\r
25825 Ext.createWidget = Ext.widget;\r
25826 /**
25827 * Convenient alias for {@link Ext#namespace Ext.namespace}.
25828 * @inheritdoc Ext#namespace
25829 * @member Ext
25830 * @method ns
25831 */\r
25832 Ext.ns = Ext.namespace;\r
25833 Class.registerPreprocessor('className', function(cls, data) {\r
25834 if ('$className' in data) {\r
25835 cls.$className = data.$className;\r
25836 cls.displayName = cls.$className;\r
25837 }\r
25838 Ext.classSystemMonitor && Ext.classSystemMonitor(cls, 'Ext.ClassManager#classNamePreprocessor', arguments);\r
25839 }, true, 'first');\r
25840 Class.registerPreprocessor('alias', function(cls, data) {\r
25841 Ext.classSystemMonitor && Ext.classSystemMonitor(cls, 'Ext.ClassManager#aliasPreprocessor', arguments);\r
25842 var prototype = cls.prototype,\r
25843 xtypes = arrayFrom(data.xtype),\r
25844 aliases = arrayFrom(data.alias),\r
25845 widgetPrefix = 'widget.',\r
25846 widgetPrefixLength = widgetPrefix.length,\r
25847 xtypesChain = Array.prototype.slice.call(prototype.xtypesChain || []),\r
25848 xtypesMap = Ext.merge({}, prototype.xtypesMap || {}),\r
25849 i, ln, alias, xtype;\r
25850 for (i = 0 , ln = aliases.length; i < ln; i++) {\r
25851 alias = aliases[i];\r
25852 if (typeof alias !== 'string' || alias.length < 1) {\r
25853 throw new Error("[Ext.define] Invalid alias of: '" + alias + "' for class: '" + name + "'; must be a valid string");\r
25854 }\r
25855 if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {\r
25856 xtype = alias.substring(widgetPrefixLength);\r
25857 Ext.Array.include(xtypes, xtype);\r
25858 }\r
25859 }\r
25860 cls.xtype = data.xtype = xtypes[0];\r
25861 data.xtypes = xtypes;\r
25862 for (i = 0 , ln = xtypes.length; i < ln; i++) {\r
25863 xtype = xtypes[i];\r
25864 if (!xtypesMap[xtype]) {\r
25865 xtypesMap[xtype] = true;\r
25866 xtypesChain.push(xtype);\r
25867 }\r
25868 }\r
25869 data.xtypesChain = xtypesChain;\r
25870 data.xtypesMap = xtypesMap;\r
25871 Ext.Function.interceptAfter(data, 'onClassCreated', function() {\r
25872 Ext.classSystemMonitor && Ext.classSystemMonitor(cls, 'Ext.ClassManager#aliasPreprocessor#afterClassCreated', arguments);\r
25873 var mixins = prototype.mixins,\r
25874 key, mixin;\r
25875 for (key in mixins) {\r
25876 if (mixins.hasOwnProperty(key)) {\r
25877 mixin = mixins[key];\r
25878 xtypes = mixin.xtypes;\r
25879 if (xtypes) {\r
25880 for (i = 0 , ln = xtypes.length; i < ln; i++) {\r
25881 xtype = xtypes[i];\r
25882 if (!xtypesMap[xtype]) {\r
25883 xtypesMap[xtype] = true;\r
25884 xtypesChain.push(xtype);\r
25885 }\r
25886 }\r
25887 }\r
25888 }\r
25889 }\r
25890 });\r
25891 for (i = 0 , ln = xtypes.length; i < ln; i++) {\r
25892 xtype = xtypes[i];\r
25893 if (typeof xtype !== 'string' || xtype.length < 1) {\r
25894 throw new Error("[Ext.define] Invalid xtype of: '" + xtype + "' for class: '" + name + "'; must be a valid non-empty string");\r
25895 }\r
25896 Ext.Array.include(aliases, widgetPrefix + xtype);\r
25897 }\r
25898 data.alias = aliases;\r
25899 }, [\r
25900 'xtype',\r
25901 'alias'\r
25902 ]);\r
25903 // load the cmd-5 style app manifest metadata now, if available...\r
25904 if (Ext.manifest) {\r
25905 var manifest = Ext.manifest,\r
25906 classes = manifest.classes,\r
25907 paths = manifest.paths,\r
25908 aliases = {},\r
25909 alternates = {},\r
25910 className, obj, name, path, baseUrl;\r
25911 if (paths) {\r
25912 // if the manifest paths were calculated as relative to the\r
25913 // bootstrap file, then we need to prepend Boot.baseUrl to the\r
25914 // paths before processing\r
25915 if (manifest.bootRelative) {\r
25916 baseUrl = Ext.Boot.baseUrl;\r
25917 for (path in paths) {\r
25918 if (paths.hasOwnProperty(path)) {\r
25919 paths[path] = baseUrl + paths[path];\r
25920 }\r
25921 }\r
25922 }\r
25923 Manager.setPath(paths);\r
25924 }\r
25925 if (classes) {\r
25926 for (className in classes) {\r
25927 alternates[className] = [];\r
25928 aliases[className] = [];\r
25929 obj = classes[className];\r
25930 if (obj.alias) {\r
25931 aliases[className] = obj.alias;\r
25932 }\r
25933 if (obj.alternates) {\r
25934 alternates[className] = obj.alternates;\r
25935 }\r
25936 }\r
25937 }\r
25938 Manager.addAlias(aliases);\r
25939 Manager.addAlternate(alternates);\r
25940 }\r
25941 return Manager;\r
25942}(Ext.Class, Ext.Function.alias, Array.prototype.slice, Ext.Array.from, Ext.global));\r
25943\r
25944/**
25945 * @class Ext.env.Browser
25946 * Provides information about browser.
25947 *
25948 * Should not be manually instantiated unless for unit-testing.
25949 * Access the global instance stored in {@link Ext.browser} instead.
25950 * @private
25951 */\r
25952(Ext.env || (Ext.env = {})).Browser = function(userAgent, publish) {\r
25953 // @define Ext.env.Browser\r
25954 // @define Ext.browser\r
25955 // @require Ext.Object\r
25956 // @require Ext.Version\r
25957 var me = this,\r
25958 browserPrefixes = Ext.Boot.browserPrefixes,\r
25959 browserNames = Ext.Boot.browserNames,\r
25960 enginePrefixes = me.enginePrefixes,\r
25961 engineNames = me.engineNames,\r
25962 browserMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(browserPrefixes).join(')|(?:') + '))([\\w\\._]+)')),\r
25963 engineMatch = userAgent.match(new RegExp('((?:' + Ext.Object.getValues(enginePrefixes).join(')|(?:') + '))([\\w\\._]+)')),\r
25964 browserName = browserNames.other,\r
25965 engineName = engineNames.other,\r
25966 browserVersion = '',\r
25967 engineVersion = '',\r
25968 majorVer = '',\r
25969 isWebView = false,\r
25970 i, prefix, mode, name, maxIEVersion;\r
25971 /**
25972 * @property {String}
25973 * Browser User Agent string.
25974 */\r
25975 me.userAgent = userAgent;\r
25976 // Edge has a userAgent with All browsers so we manage it separately\r
25977 // "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240"\r
25978 if (/Edge\//.test(userAgent)) {\r
25979 browserMatch = userAgent.match(/(Edge\/)([\w.]+)/);\r
25980 }\r
25981 if (browserMatch) {\r
25982 browserName = browserNames[Ext.Object.getKey(browserPrefixes, browserMatch[1])];\r
25983 if (browserName === 'Safari' && /^Opera/.test(userAgent)) {\r
25984 // Prevent Opera 12 and earlier from being incorrectly reported as Safari\r
25985 browserName = 'Opera';\r
25986 }\r
25987 browserVersion = new Ext.Version(browserMatch[2]);\r
25988 }\r
25989 if (engineMatch) {\r
25990 engineName = engineNames[Ext.Object.getKey(enginePrefixes, engineMatch[1])];\r
25991 engineVersion = new Ext.Version(engineMatch[2]);\r
25992 }\r
25993 if (engineName === 'Trident' && browserName !== 'IE') {\r
25994 browserName = 'IE';\r
25995 var version = userAgent.match(/.*rv:(\d+.\d+)/);\r
25996 if (version && version.length) {\r
25997 version = version[1];\r
25998 browserVersion = new Ext.Version(version);\r
25999 }\r
26000 }\r
26001 if (browserName && browserVersion) {\r
26002 Ext.setVersion(browserName, browserVersion);\r
26003 }\r
26004 /**
26005 * @property chromeVersion
26006 * The current version of Chrome (0 if the browser is not Chrome).
26007 * @readonly
26008 * @type Number
26009 * @member Ext
26010 */\r
26011 /**
26012 * @property firefoxVersion
26013 * The current version of Firefox (0 if the browser is not Firefox).
26014 * @readonly
26015 * @type Number
26016 * @member Ext
26017 */\r
26018 /**
26019 * @property ieVersion
26020 * The current version of IE (0 if the browser is not IE). This does not account
26021 * for the documentMode of the current page, which is factored into {@link #isIE8},
26022 * and {@link #isIE9}. Thus this is not always true:
26023 *
26024 * Ext.isIE8 == (Ext.ieVersion == 8)
26025 *
26026 * @readonly
26027 * @type Number
26028 * @member Ext
26029 */\r
26030 /**
26031 * @property isChrome
26032 * True if the detected browser is Chrome.
26033 * @readonly
26034 * @type Boolean
26035 * @member Ext
26036 */\r
26037 /**
26038 * @property isGecko
26039 * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
26040 * @readonly
26041 * @type Boolean
26042 * @member Ext
26043 */\r
26044 /**
26045 * @property isIE
26046 * True if the detected browser is Internet Explorer.
26047 * @readonly
26048 * @type Boolean
26049 * @member Ext
26050 */\r
26051 /**
26052 * @property isIE8
26053 * True if the detected browser is Internet Explorer 8.x.
26054 * @readonly
26055 * @type Boolean
26056 * @member Ext
26057 */\r
26058 /**
26059 * @property isIE8m
26060 * True if the detected browser is Internet Explorer 8.x or lower.
26061 * @readonly
26062 * @type Boolean
26063 * @member Ext
26064 */\r
26065 /**
26066 * @property isIE8p
26067 * True if the detected browser is Internet Explorer 8.x or higher.
26068 * @readonly
26069 * @type Boolean
26070 * @member Ext
26071 */\r
26072 /**
26073 * @property isIE9
26074 * True if the detected browser is Internet Explorer 9.x.
26075 * @readonly
26076 * @type Boolean
26077 * @member Ext
26078 */\r
26079 /**
26080 * @property isIE9m
26081 * True if the detected browser is Internet Explorer 9.x or lower.
26082 * @readonly
26083 * @type Boolean
26084 * @member Ext
26085 */\r
26086 /**
26087 * @property isIE9p
26088 * True if the detected browser is Internet Explorer 9.x or higher.
26089 * @readonly
26090 * @type Boolean
26091 * @member Ext
26092 */\r
26093 /**
26094 * @property isIE10
26095 * True if the detected browser is Internet Explorer 10.x.
26096 * @readonly
26097 * @type Boolean
26098 * @member Ext
26099 */\r
26100 /**
26101 * @property isIE10m
26102 * True if the detected browser is Internet Explorer 10.x or lower.
26103 * @readonly
26104 * @type Boolean
26105 * @member Ext
26106 */\r
26107 /**
26108 * @property isIE10p
26109 * True if the detected browser is Internet Explorer 10.x or higher.
26110 * @readonly
26111 * @type Boolean
26112 * @member Ext
26113 */\r
26114 /**
26115 * @property isIE11
26116 * True if the detected browser is Internet Explorer 11.x.
26117 * @readonly
26118 * @type Boolean
26119 * @member Ext
26120 */\r
26121 /**
26122 * @property isIE11m
26123 * True if the detected browser is Internet Explorer 11.x or lower.
26124 * @readonly
26125 * @type Boolean
26126 * @member Ext
26127 */\r
26128 /**
26129 * @property isIE11p
26130 * True if the detected browser is Internet Explorer 11.x or higher.
26131 * @readonly
26132 * @type Boolean
26133 * @member Ext
26134 */\r
26135 /**
26136 * @property isLinux
26137 * True if the detected platform is Linux.
26138 * @readonly
26139 * @type Boolean
26140 * @member Ext
26141 */\r
26142 /**
26143 * @property isMac
26144 * True if the detected platform is Mac OS.
26145 * @readonly
26146 * @type Boolean
26147 * @member Ext
26148 */\r
26149 /**
26150 * @property isOpera
26151 * True if the detected browser is Opera.
26152 * @readonly
26153 * @type Boolean
26154 * @member Ext
26155 */\r
26156 /**
26157 * @property isSafari
26158 * True if the detected browser is Safari.
26159 * @readonly
26160 * @type Boolean
26161 * @member Ext
26162 */\r
26163 /**
26164 * @property isWebKit
26165 * True if the detected browser uses WebKit.
26166 * @readonly
26167 * @type Boolean
26168 * @member Ext
26169 */\r
26170 /**
26171 * @property isWindows
26172 * True if the detected platform is Windows.
26173 * @readonly
26174 * @type Boolean
26175 * @member Ext
26176 */\r
26177 /**
26178 * @property operaVersion
26179 * The current version of Opera (0 if the browser is not Opera).
26180 * @readonly
26181 * @type Number
26182 * @member Ext
26183 */\r
26184 /**
26185 * @property safariVersion
26186 * The current version of Safari (0 if the browser is not Safari).
26187 * @readonly
26188 * @type Number
26189 * @member Ext
26190 */\r
26191 /**
26192 * @property webKitVersion
26193 * The current version of WebKit (0 if the browser does not use WebKit).
26194 * @readonly
26195 * @type Number
26196 * @member Ext
26197 */\r
26198 // Facebook changes the userAgent when you view a website within their iOS app. For some reason, the strip out information\r
26199 // about the browser, so we have to detect that and fake it...\r
26200 if (userAgent.match(/FB/) && browserName === "Other") {\r
26201 browserName = browserNames.safari;\r
26202 engineName = engineNames.webkit;\r
26203 }\r
26204 if (userAgent.match(/Android.*Chrome/g)) {\r
26205 browserName = 'ChromeMobile';\r
26206 }\r
26207 if (userAgent.match(/OPR/)) {\r
26208 browserName = 'Opera';\r
26209 browserMatch = userAgent.match(/OPR\/(\d+.\d+)/);\r
26210 browserVersion = new Ext.Version(browserMatch[1]);\r
26211 }\r
26212 Ext.apply(this, {\r
26213 engineName: engineName,\r
26214 engineVersion: engineVersion,\r
26215 name: browserName,\r
26216 version: browserVersion\r
26217 });\r
26218 this.setFlag(browserName, true, publish);\r
26219 // e.g., Ext.isIE\r
26220 if (browserVersion) {\r
26221 majorVer = browserVersion.getMajor() || '';\r
26222 if (me.is.IE) {\r
26223 majorVer = parseInt(majorVer, 10);\r
26224 mode = document.documentMode;\r
26225 // IE's Developer Tools allows switching of Browser Mode (userAgent) and\r
26226 // Document Mode (actual behavior) independently. While this makes no real\r
26227 // sense, the bottom line is that document.documentMode holds the key to\r
26228 // getting the proper "version" determined. That value is always 5 when in\r
26229 // Quirks Mode.\r
26230 if (mode === 7 || (majorVer === 7 && mode !== 8 && mode !== 9 && mode !== 10)) {\r
26231 majorVer = 7;\r
26232 } else if (mode === 8 || (majorVer === 8 && mode !== 8 && mode !== 9 && mode !== 10)) {\r
26233 majorVer = 8;\r
26234 } else if (mode === 9 || (majorVer === 9 && mode !== 7 && mode !== 8 && mode !== 10)) {\r
26235 majorVer = 9;\r
26236 } else if (mode === 10 || (majorVer === 10 && mode !== 7 && mode !== 8 && mode !== 9)) {\r
26237 majorVer = 10;\r
26238 } else if (mode === 11 || (majorVer === 11 && mode !== 7 && mode !== 8 && mode !== 9 && mode !== 10)) {\r
26239 majorVer = 11;\r
26240 }\r
26241 maxIEVersion = Math.max(majorVer, Ext.Boot.maxIEVersion);\r
26242 for (i = 7; i <= maxIEVersion; ++i) {\r
26243 prefix = 'isIE' + i;\r
26244 if (majorVer <= i) {\r
26245 Ext[prefix + 'm'] = true;\r
26246 }\r
26247 if (majorVer === i) {\r
26248 Ext[prefix] = true;\r
26249 }\r
26250 if (majorVer >= i) {\r
26251 Ext[prefix + 'p'] = true;\r
26252 }\r
26253 }\r
26254 }\r
26255 if (me.is.Opera && parseInt(majorVer, 10) <= 12) {\r
26256 Ext.isOpera12m = true;\r
26257 }\r
26258 Ext.chromeVersion = Ext.isChrome ? majorVer : 0;\r
26259 Ext.firefoxVersion = Ext.isFirefox ? majorVer : 0;\r
26260 Ext.ieVersion = Ext.isIE ? majorVer : 0;\r
26261 Ext.operaVersion = Ext.isOpera ? majorVer : 0;\r
26262 Ext.safariVersion = Ext.isSafari ? majorVer : 0;\r
26263 Ext.webKitVersion = Ext.isWebKit ? majorVer : 0;\r
26264 this.setFlag(browserName + majorVer, true, publish);\r
26265 // Ext.isIE10\r
26266 this.setFlag(browserName + browserVersion.getShortVersion());\r
26267 }\r
26268 for (i in browserNames) {\r
26269 if (browserNames.hasOwnProperty(i)) {\r
26270 name = browserNames[i];\r
26271 this.setFlag(name, browserName === name);\r
26272 }\r
26273 }\r
26274 this.setFlag(name);\r
26275 if (engineVersion) {\r
26276 this.setFlag(engineName + (engineVersion.getMajor() || ''));\r
26277 this.setFlag(engineName + engineVersion.getShortVersion());\r
26278 }\r
26279 for (i in engineNames) {\r
26280 if (engineNames.hasOwnProperty(i)) {\r
26281 name = engineNames[i];\r
26282 this.setFlag(name, engineName === name, publish);\r
26283 }\r
26284 }\r
26285 this.setFlag('Standalone', !!navigator.standalone);\r
26286 this.setFlag('Ripple', !!document.getElementById("tinyhippos-injected") && !Ext.isEmpty(window.top.ripple));\r
26287 this.setFlag('WebWorks', !!window.blackberry);\r
26288 if (window.PhoneGap !== undefined || window.Cordova !== undefined || window.cordova !== undefined) {\r
26289 isWebView = true;\r
26290 this.setFlag('PhoneGap');\r
26291 this.setFlag('Cordova');\r
26292 }\r
26293 // Check if running in UIWebView\r
26294 if (/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)(?!.*FBAN)/i.test(userAgent)) {\r
26295 isWebView = true;\r
26296 }\r
26297 // Flag to check if it we are in the WebView\r
26298 this.setFlag('WebView', isWebView);\r
26299 /**
26300 * @property {Boolean}
26301 * `true` if browser is using strict mode.
26302 */\r
26303 this.isStrict = Ext.isStrict = document.compatMode === "CSS1Compat";\r
26304 /**
26305 * @property {Boolean}
26306 * `true` if page is running over SSL.
26307 */\r
26308 this.isSecure = Ext.isSecure;\r
26309 // IE10Quirks, Chrome26Strict, etc.\r
26310 this.identity = browserName + majorVer + (this.isStrict ? 'Strict' : 'Quirks');\r
26311};\r
26312Ext.env.Browser.prototype = {\r
26313 constructor: Ext.env.Browser,\r
26314 engineNames: {\r
26315 webkit: 'WebKit',\r
26316 gecko: 'Gecko',\r
26317 presto: 'Presto',\r
26318 trident: 'Trident',\r
26319 other: 'Other'\r
26320 },\r
26321 enginePrefixes: {\r
26322 webkit: 'AppleWebKit/',\r
26323 gecko: 'Gecko/',\r
26324 presto: 'Presto/',\r
26325 trident: 'Trident/'\r
26326 },\r
26327 styleDashPrefixes: {\r
26328 WebKit: '-webkit-',\r
26329 Gecko: '-moz-',\r
26330 Trident: '-ms-',\r
26331 Presto: '-o-',\r
26332 Other: ''\r
26333 },\r
26334 stylePrefixes: {\r
26335 WebKit: 'Webkit',\r
26336 Gecko: 'Moz',\r
26337 Trident: 'ms',\r
26338 Presto: 'O',\r
26339 Other: ''\r
26340 },\r
26341 propertyPrefixes: {\r
26342 WebKit: 'webkit',\r
26343 Gecko: 'moz',\r
26344 Trident: 'ms',\r
26345 Presto: 'o',\r
26346 Other: ''\r
26347 },\r
26348 // scope: Ext.env.Browser.prototype\r
26349 /**
26350 * A "hybrid" property, can be either accessed as a method call, for example:
26351 *
26352 * if (Ext.browser.is('IE')) {
26353 * // ...
26354 * }
26355 *
26356 * Or as an object with Boolean properties, for example:
26357 *
26358 * if (Ext.browser.is.IE) {
26359 * // ...
26360 * }
26361 *
26362 * Versions can be conveniently checked as well. For example:
26363 *
26364 * if (Ext.browser.is.IE10) {
26365 * // Equivalent to (Ext.browser.is.IE && Ext.browser.version.equals(10))
26366 * }
26367 *
26368 * __Note:__ Only {@link Ext.Version#getMajor major component} and {@link Ext.Version#getShortVersion simplified}
26369 * value of the version are available via direct property checking.
26370 *
26371 * Supported values are:
26372 *
26373 * - IE
26374 * - Firefox
26375 * - Safari
26376 * - Chrome
26377 * - Opera
26378 * - WebKit
26379 * - Gecko
26380 * - Presto
26381 * - Trident
26382 * - WebView
26383 * - Other
26384 *
26385 * @param {String} name The OS name to check.
26386 * @return {Boolean}
26387 */\r
26388 is: function(name) {\r
26389 return !!this.is[name];\r
26390 },\r
26391 /**
26392 * The full name of the current browser.
26393 * Possible values are:
26394 *
26395 * - IE
26396 * - Firefox
26397 * - Safari
26398 * - Chrome
26399 * - Opera
26400 * - Other
26401 * @type String
26402 * @readonly
26403 */\r
26404 name: null,\r
26405 /**
26406 * Refer to {@link Ext.Version}.
26407 * @type Ext.Version
26408 * @readonly
26409 */\r
26410 version: null,\r
26411 /**
26412 * The full name of the current browser's engine.
26413 * Possible values are:
26414 *
26415 * - WebKit
26416 * - Gecko
26417 * - Presto
26418 * - Trident
26419 * - Other
26420 * @type String
26421 * @readonly
26422 */\r
26423 engineName: null,\r
26424 /**
26425 * Refer to {@link Ext.Version}.
26426 * @type Ext.Version
26427 * @readonly
26428 */\r
26429 engineVersion: null,\r
26430 setFlag: function(name, value, publish) {\r
26431 if (value === undefined) {\r
26432 value = true;\r
26433 }\r
26434 this.is[name] = value;\r
26435 this.is[name.toLowerCase()] = value;\r
26436 if (publish) {\r
26437 Ext['is' + name] = value;\r
26438 }\r
26439 return this;\r
26440 },\r
26441 getStyleDashPrefix: function() {\r
26442 return this.styleDashPrefixes[this.engineName];\r
26443 },\r
26444 getStylePrefix: function() {\r
26445 return this.stylePrefixes[this.engineName];\r
26446 },\r
26447 getVendorProperyName: function(name) {\r
26448 var prefix = this.propertyPrefixes[this.engineName];\r
26449 if (prefix.length > 0) {\r
26450 return prefix + Ext.String.capitalize(name);\r
26451 }\r
26452 return name;\r
26453 },\r
26454 getPreferredTranslationMethod: function(config) {\r
26455 if (typeof config === 'object' && 'translationMethod' in config && config.translationMethod !== 'auto') {\r
26456 return config.translationMethod;\r
26457 } else {\r
26458 return 'csstransform';\r
26459 }\r
26460 }\r
26461};\r
26462/**
26463 * @class Ext.browser
26464 * @extends Ext.env.Browser
26465 * @singleton
26466 * Provides useful information about the current browser.
26467 *
26468 * Example:
26469 *
26470 * if (Ext.browser.is.IE) {
26471 * // IE specific code here
26472 * }
26473 *
26474 * if (Ext.browser.is.WebKit) {
26475 * // WebKit specific code here
26476 * }
26477 *
26478 * console.log("Version " + Ext.browser.version);
26479 *
26480 * For a full list of supported values, refer to {@link #is} property/method.
26481 *
26482 */\r
26483(function(userAgent) {\r
26484 Ext.browser = new Ext.env.Browser(userAgent, true);\r
26485 Ext.userAgent = userAgent.toLowerCase();\r
26486 /**
26487 * @property {String} SSL_SECURE_URL
26488 * URL to a blank file used by Ext when in secure mode for iframe src and onReady src
26489 * to prevent the IE insecure content warning (`'about:blank'`, except for IE
26490 * in secure mode, which is `'javascript:""'`).
26491 * @member Ext
26492 */\r
26493 Ext.SSL_SECURE_URL = Ext.isSecure && Ext.isIE ? 'javascript:\'\'' : 'about:blank';\r
26494}(// jshint ignore:line\r
26495Ext.global.navigator.userAgent));\r
26496\r
26497/**
26498 * Provides information about operating system environment.
26499 *
26500 * Should not be manually instantiated unless for unit-testing.
26501 * Access the global instance stored in {@link Ext.os} instead.
26502 * @private
26503 */\r
26504Ext.env.OS = function(userAgent, platform, browserScope) {\r
26505 // @define Ext.env.OS\r
26506 // @define Ext.os\r
26507 // @require Ext.Version\r
26508 // @require Ext.env.Browser\r
26509 var me = this,\r
26510 names = Ext.Boot.osNames,\r
26511 prefixes = Ext.Boot.osPrefixes,\r
26512 name,\r
26513 version = '',\r
26514 is = me.is,\r
26515 i, prefix, match, item, match1;\r
26516 browserScope = browserScope || Ext.browser;\r
26517 for (i in prefixes) {\r
26518 if (prefixes.hasOwnProperty(i)) {\r
26519 prefix = prefixes[i];\r
26520 match = userAgent.match(new RegExp('(?:' + prefix + ')([^\\s;]+)'));\r
26521 if (match) {\r
26522 name = names[i];\r
26523 match1 = match[1];\r
26524 // This is here because some HTC android devices show an OSX Snow Leopard userAgent by default.\r
26525 // And the Kindle Fire doesn't have any indicator of Android as the OS in its User Agent\r
26526 if (match1 && match1 === "HTC_") {\r
26527 version = new Ext.Version("2.3");\r
26528 } else if (match1 && match1 === "Silk/") {\r
26529 version = new Ext.Version("2.3");\r
26530 } else {\r
26531 version = new Ext.Version(match[match.length - 1]);\r
26532 }\r
26533 break;\r
26534 }\r
26535 }\r
26536 }\r
26537 if (!name) {\r
26538 name = names[(userAgent.toLowerCase().match(/mac|win|linux/) || [\r
26539 'other'\r
26540 ])[0]];\r
26541 version = new Ext.Version('');\r
26542 }\r
26543 this.name = name;\r
26544 this.version = version;\r
26545 if (platform) {\r
26546 this.setFlag(platform.replace(/ simulator$/i, ''));\r
26547 }\r
26548 this.setFlag(name);\r
26549 if (version) {\r
26550 this.setFlag(name + (version.getMajor() || ''));\r
26551 this.setFlag(name + version.getShortVersion());\r
26552 }\r
26553 for (i in names) {\r
26554 if (names.hasOwnProperty(i)) {\r
26555 item = names[i];\r
26556 if (!is.hasOwnProperty(name)) {\r
26557 this.setFlag(item, (name === item));\r
26558 }\r
26559 }\r
26560 }\r
26561 // Detect if the device is the iPhone 5.\r
26562 if (this.name === "iOS" && window.screen.height === 568) {\r
26563 this.setFlag('iPhone5');\r
26564 }\r
26565 if (browserScope.is.Safari || browserScope.is.Silk) {\r
26566 // Ext.browser.version.shortVersion == 501 is for debugging off device\r
26567 if (this.is.Android2 || this.is.Android3 || browserScope.version.shortVersion === 501) {\r
26568 browserScope.setFlag("AndroidStock");\r
26569 }\r
26570 if (this.is.Android4) {\r
26571 browserScope.setFlag("AndroidStock");\r
26572 browserScope.setFlag("AndroidStock4");\r
26573 }\r
26574 }\r
26575};\r
26576Ext.env.OS.prototype = {\r
26577 constructor: Ext.env.OS,\r
26578 /**
26579 * A "hybrid" property, can be either accessed as a method call, i.e:
26580 *
26581 * if (Ext.os.is('Android')) {
26582 * // ...
26583 * }
26584 *
26585 * or as an object with boolean properties, i.e:
26586 *
26587 * if (Ext.os.is.Android) {
26588 * // ...
26589 * }
26590 *
26591 * Versions can be conveniently checked as well. For example:
26592 *
26593 * if (Ext.os.is.Android2) {
26594 * // Equivalent to (Ext.os.is.Android && Ext.os.version.equals(2))
26595 * }
26596 *
26597 * if (Ext.os.is.iOS32) {
26598 * // Equivalent to (Ext.os.is.iOS && Ext.os.version.equals(3.2))
26599 * }
26600 *
26601 * Note that only {@link Ext.Version#getMajor major component} and {@link Ext.Version#getShortVersion simplified}
26602 * value of the version are available via direct property checking. Supported values are:
26603 *
26604 * - iOS
26605 * - iPad
26606 * - iPhone
26607 * - iPhone5 (also true for 4in iPods).
26608 * - iPod
26609 * - Android
26610 * - WebOS
26611 * - BlackBerry
26612 * - Bada
26613 * - MacOS
26614 * - Windows
26615 * - Linux
26616 * - Other
26617 * @member Ext.os
26618 * @param {String} name The OS name to check.
26619 * @return {Boolean}
26620 */\r
26621 is: function(name) {\r
26622 return !!this[name];\r
26623 },\r
26624 /**
26625 * @property {String} [name=null]
26626 * @readonly
26627 * @member Ext.os
26628 * The full name of the current operating system. Possible values are:
26629 *
26630 * - iOS
26631 * - Android
26632 * - WebOS
26633 * - BlackBerry,
26634 * - MacOS
26635 * - Windows
26636 * - Linux
26637 * - Other
26638 */\r
26639 name: null,\r
26640 /**
26641 * @property {Ext.Version} [version=null]
26642 * Refer to {@link Ext.Version}
26643 * @member Ext.os
26644 * @readonly
26645 */\r
26646 version: null,\r
26647 setFlag: function(name, value) {\r
26648 if (value === undefined) {\r
26649 value = true;\r
26650 }\r
26651 if (this.flags) {\r
26652 this.flags[name] = value;\r
26653 }\r
26654 this.is[name] = value;\r
26655 this.is[name.toLowerCase()] = value;\r
26656 return this;\r
26657 }\r
26658};\r
26659(function() {\r
26660 var navigation = Ext.global.navigator,\r
26661 userAgent = navigation.userAgent,\r
26662 OS = Ext.env.OS,\r
26663 is = (Ext.is || (Ext.is = {})),\r
26664 osEnv, osName, deviceType;\r
26665 OS.prototype.flags = is;\r
26666 /**
26667 * @class Ext.os
26668 * @extends Ext.env.OS
26669 * @singleton
26670 * Provides useful information about the current operating system environment.
26671 *
26672 * Example:
26673 *
26674 * if (Ext.os.is.Windows) {
26675 * // Windows specific code here
26676 * }
26677 *
26678 * if (Ext.os.is.iOS) {
26679 * // iPad, iPod, iPhone, etc.
26680 * }
26681 *
26682 * console.log("Version " + Ext.os.version);
26683 *
26684 * For a full list of supported values, refer to the {@link #is} property/method.
26685 *
26686 */\r
26687 Ext.os = osEnv = new OS(userAgent, navigation.platform);\r
26688 osName = osEnv.name;\r
26689 // A couple compatible flavors:\r
26690 Ext['is' + osName] = true;\r
26691 // e.g., Ext.isWindows\r
26692 Ext.isMac = is.Mac = is.MacOS;\r
26693 var search = window.location.search.match(/deviceType=(Tablet|Phone)/),\r
26694 nativeDeviceType = window.deviceType;\r
26695 // Override deviceType by adding a get variable of deviceType. NEEDED FOR DOCS APP.\r
26696 // E.g: example/kitchen-sink.html?deviceType=Phone\r
26697 if (search && search[1]) {\r
26698 deviceType = search[1];\r
26699 } else if (nativeDeviceType === 'iPhone') {\r
26700 deviceType = 'Phone';\r
26701 } else if (nativeDeviceType === 'iPad') {\r
26702 deviceType = 'Tablet';\r
26703 } else {\r
26704 if (!osEnv.is.Android && !osEnv.is.iOS && !osEnv.is.WindowsPhone && /Windows|Linux|MacOS/.test(osName)) {\r
26705 deviceType = 'Desktop';\r
26706 // always set it to false when you are on a desktop not using Ripple Emulation\r
26707 Ext.browser.is.WebView = !!Ext.browser.is.Ripple;\r
26708 } else if (osEnv.is.iPad || osEnv.is.RIMTablet || osEnv.is.Android3 || Ext.browser.is.Silk || (osEnv.is.Android && userAgent.search(/mobile/i) === -1)) {\r
26709 deviceType = 'Tablet';\r
26710 } else {\r
26711 deviceType = 'Phone';\r
26712 }\r
26713 }\r
26714 /**
26715 * @property {String} deviceType
26716 * The generic type of the current device.
26717 *
26718 * Possible values:
26719 *
26720 * - Phone
26721 * - Tablet
26722 * - Desktop
26723 *
26724 * For testing purposes the deviceType can be overridden by adding
26725 * a deviceType parameter to the URL of the page, like so:
26726 *
26727 * http://localhost/mypage.html?deviceType=Tablet
26728 *
26729 * @member Ext.os
26730 */\r
26731 osEnv.setFlag(deviceType, true);\r
26732 osEnv.deviceType = deviceType;\r
26733 delete OS.prototype.flags;\r
26734}());\r
26735\r
26736/**
26737 * @class Ext.feature
26738 * @singleton
26739 *
26740 * A simple class to verify if a browser feature exists or not on the current device.
26741 *
26742 * if (Ext.feature.has.Canvas) {
26743 * // do some cool things with canvas here
26744 * }
26745 *
26746 * See the {@link #has} property/method for details of the features that can be detected.
26747 *
26748 */\r
26749Ext.feature = {\r
26750 // @define Ext.env.Feature\r
26751 // @define Ext.feature\r
26752 // @define Ext.supports\r
26753 // @require Ext.String\r
26754 // @require Ext.env.Browser\r
26755 // @require Ext.env.OS\r
26756 /**
26757 * @method has
26758 * @member Ext.feature
26759 * Verifies if a browser feature exists or not on the current device.
26760 *
26761 * A "hybrid" property, can be either accessed as a method call, i.e:
26762 *
26763 * if (Ext.feature.has('Canvas')) {
26764 * // ...
26765 * }
26766 *
26767 * or as an object with boolean properties, i.e:
26768 *
26769 * if (Ext.feature.has.Canvas) {
26770 * // ...
26771 * }
26772 *
26773 * For possible properties/parameter values see `Ext.supports`.
26774 *
26775 * @param {String} name The feature name to check.
26776 * @return {Boolean}
26777 */\r
26778 has: function(name) {\r
26779 return !!this.has[name];\r
26780 },\r
26781 testElements: {},\r
26782 getTestElement: function(tag, createNew) {\r
26783 if (tag === undefined) {\r
26784 tag = 'div';\r
26785 } else if (typeof tag !== 'string') {\r
26786 return tag;\r
26787 }\r
26788 if (createNew) {\r
26789 return document.createElement(tag);\r
26790 }\r
26791 if (!this.testElements[tag]) {\r
26792 this.testElements[tag] = document.createElement(tag);\r
26793 }\r
26794 return this.testElements[tag];\r
26795 },\r
26796 isStyleSupported: function(name, tag) {\r
26797 var elementStyle = this.getTestElement(tag).style,\r
26798 cName = Ext.String.capitalize(name);\r
26799 if (typeof elementStyle[name] !== 'undefined' || typeof elementStyle[Ext.browser.getStylePrefix(name) + cName] !== 'undefined') {\r
26800 return true;\r
26801 }\r
26802 return false;\r
26803 },\r
26804 isStyleSupportedWithoutPrefix: function(name, tag) {\r
26805 var elementStyle = this.getTestElement(tag).style;\r
26806 if (typeof elementStyle[name] !== 'undefined') {\r
26807 return true;\r
26808 }\r
26809 return false;\r
26810 },\r
26811 isEventSupported: function(name, tag) {\r
26812 if (tag === undefined) {\r
26813 tag = window;\r
26814 }\r
26815 var element = this.getTestElement(tag),\r
26816 eventName = 'on' + name.toLowerCase(),\r
26817 isSupported = (eventName in element);\r
26818 if (!isSupported) {\r
26819 if (element.setAttribute && element.removeAttribute) {\r
26820 element.setAttribute(eventName, '');\r
26821 isSupported = typeof element[eventName] === 'function';\r
26822 if (typeof element[eventName] !== 'undefined') {\r
26823 element[eventName] = undefined;\r
26824 }\r
26825 element.removeAttribute(eventName);\r
26826 }\r
26827 }\r
26828 return isSupported;\r
26829 },\r
26830 // This is a local copy of certain logic from Element.getStyle\r
26831 // to break a dependancy between the supports mechanism and Element\r
26832 // use this instead of element references to check for styling info\r
26833 getStyle: function(element, styleName) {\r
26834 var view = element.ownerDocument.defaultView,\r
26835 style = (view ? view.getComputedStyle(element, null) : element.currentStyle);\r
26836 return (style || element.style)[styleName];\r
26837 },\r
26838 getSupportedPropertyName: function(object, name) {\r
26839 var vendorName = Ext.browser.getVendorProperyName(name);\r
26840 if (vendorName in object) {\r
26841 return vendorName;\r
26842 } else if (name in object) {\r
26843 return name;\r
26844 }\r
26845 return null;\r
26846 },\r
26847 /**
26848 * Runs feature detection routines and sets the various flags. This is called when
26849 * the scripts loads (very early) and again at {@link Ext#onReady}. Some detections
26850 * can be run immediately. Others that require the document body will not run until
26851 * domready (these have the `ready` flag set).
26852 *
26853 * Each test is run only once, so calling this method from an onReady function is safe
26854 * and ensures that all flags have been set.
26855 * @private
26856 */\r
26857 detect: function(isReady) {\r
26858 var me = this,\r
26859 doc = document,\r
26860 toRun = me.toRun || me.tests,\r
26861 n = toRun.length,\r
26862 div = doc.createElement('div'),\r
26863 notRun = [],\r
26864 supports = Ext.supports,\r
26865 has = me.has,\r
26866 name, names, test, vector, value;\r
26867 // Only the legacy browser tests use this div so clip this out if we don't need\r
26868 // to use it.\r
26869 div.innerHTML = '<div style="height:30px;width:50px;">' + '<div style="height:20px;width:20px;"></div>' + '</div>' + '<div style="width: 200px; height: 200px; position: relative; padding: 5px;">' + '<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>' + '</div>' + '<div style="position: absolute; left: 10%; top: 10%;"></div>' + '<div style="float:left; background-color:transparent;"></div>';\r
26870 if (isReady) {\r
26871 doc.body.appendChild(div);\r
26872 }\r
26873 vector = me.preDetected[Ext.browser.identity] || [];\r
26874 while (n--) {\r
26875 test = toRun[n];\r
26876 value = vector[n];\r
26877 name = test.name;\r
26878 names = test.names;\r
26879 if (value === undefined) {\r
26880 if (!isReady && test.ready) {\r
26881 // test requires domready state\r
26882 notRun.push(test);\r
26883 \r
26884 continue;\r
26885 }\r
26886 value = test.fn.call(me, doc, div);\r
26887 }\r
26888 // Store test results on Ext.supports and Ext.feature.has\r
26889 if (name) {\r
26890 supports[name] = has[name] = value;\r
26891 } else if (names) {\r
26892 while (names.length) {\r
26893 name = names.pop();\r
26894 supports[name] = has[name] = value;\r
26895 }\r
26896 }\r
26897 }\r
26898 if (isReady) {\r
26899 doc.body.removeChild(div);\r
26900 }\r
26901 me.toRun = notRun;\r
26902 },\r
26903 //</debug>\r
26904 report: function() {\r
26905 var values = [],\r
26906 len = this.tests.length,\r
26907 i;\r
26908 for (i = 0; i < len; ++i) {\r
26909 values.push(this.has[this.tests[i].name] ? 1 : 0);\r
26910 }\r
26911 Ext.log(Ext.browser.identity + ': [' + values.join(',') + ']');\r
26912 },\r
26913 //</debug>\r
26914 preDetected: {},\r
26915 // TODO\r
26916 /**
26917 * @class Ext.supports
26918 *
26919 * Contains information about features supported in the current environment as well
26920 * as bugs detected.
26921 *
26922 * @singleton
26923 */\r
26924 tests: [\r
26925 {\r
26926 /**
26927 * @property CloneNodeCopiesExpando `true` if the native DOM cloneNode method copies
26928 * expando properties to the newly cloned node.
26929 *
26930 * This property is available at application boot time, before document ready.
26931 * @type {Boolean}
26932 */\r
26933 name: 'CloneNodeCopiesExpando',\r
26934 fn: function() {\r
26935 var el = document.createElement('div');\r
26936 el.expandoProp = {};\r
26937 return el.cloneNode().expandoProp === el.expandoProp;\r
26938 }\r
26939 },\r
26940 {\r
26941 /**
26942 * @property CSSPointerEvents `true` if document environment supports the CSS3
26943 * pointer-events style.
26944 *
26945 * This property is available at application boot time, before document ready.
26946 * @type {Boolean}
26947 */\r
26948 name: 'CSSPointerEvents',\r
26949 fn: function(doc) {\r
26950 return 'pointerEvents' in doc.documentElement.style;\r
26951 }\r
26952 },\r
26953 {\r
26954 /**
26955 * @property CSS3BoxShadow `true` if document environment supports the CSS3
26956 * box-shadow style.
26957 *
26958 * This property is available at application boot time, before document ready.
26959 * @type {Boolean}
26960 */\r
26961 name: 'CSS3BoxShadow',\r
26962 fn: function(doc) {\r
26963 return 'boxShadow' in doc.documentElement.style || 'WebkitBoxShadow' in doc.documentElement.style || 'MozBoxShadow' in doc.documentElement.style;\r
26964 }\r
26965 },\r
26966 {\r
26967 name: 'CSS3NegationSelector',\r
26968 fn: function(doc) {\r
26969 try {\r
26970 doc.querySelectorAll("foo:not(bar)");\r
26971 } catch (e) {\r
26972 return false;\r
26973 }\r
26974 return true;\r
26975 }\r
26976 },\r
26977 {\r
26978 /**
26979 * @property ClassList `true` if document environment supports the HTML5
26980 * classList API.
26981 *
26982 * This property is available at application boot time, before document ready.
26983 * @type {Boolean}
26984 */\r
26985 name: 'ClassList',\r
26986 fn: function(doc) {\r
26987 return !!doc.documentElement.classList;\r
26988 }\r
26989 },\r
26990 {\r
26991 /**
26992 * @property Canvas `true` if the device supports Canvas.
26993 *
26994 * This property is available at application boot time, before document ready.
26995 * @type {Boolean}
26996 */\r
26997 name: 'Canvas',\r
26998 fn: function() {\r
26999 var element = this.getTestElement('canvas');\r
27000 return !!(element && element.getContext && element.getContext('2d'));\r
27001 }\r
27002 },\r
27003 {\r
27004 /**
27005 * @property Svg `true` if the device supports SVG.
27006 *
27007 * This property is available at application boot time, before document ready.
27008 * @type {Boolean}
27009 */\r
27010 name: 'Svg',\r
27011 fn: function(doc) {\r
27012 return !!(doc.createElementNS && !!doc.createElementNS("http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect);\r
27013 }\r
27014 },\r
27015 {\r
27016 /**
27017 * @property Vml `true` if the device supports VML.
27018 * @type {Boolean}
27019 *
27020 * This property is available at application boot time, before document ready.
27021 */\r
27022 name: 'Vml',\r
27023 fn: function() {\r
27024 var element = this.getTestElement(),\r
27025 ret = false;\r
27026 element.innerHTML = "<!--[if vml]><br><![endif]-->";\r
27027 ret = (element.childNodes.length === 1);\r
27028 element.innerHTML = "";\r
27029 return ret;\r
27030 }\r
27031 },\r
27032 {\r
27033 /**
27034 * @property touchScroll
27035 * @type {Number}
27036 *
27037 * This property is used to trigger touch scrolling support via Ext.scroll.TouchScroller.
27038 * There are three possible values for this property:
27039 *
27040 * - `0` - Touch scrolling disabled.
27041 *
27042 * - `1` - enables partial scroller support. In this mode the touch scroller
27043 * simply controls the scroll positions of naturally overflowing elements.
27044 * This mode is typically used on multi-input devices where native scrolling
27045 * using the mouse is desired, but native touch-scrolling must be disabled to
27046 * avoid cancelling gesture recognition inside of scrollable elements (e.g.
27047 * IE10 and up on touch-screen laptops and tablets)
27048 *
27049 * - `2` - enables full scroller support. In this mode, scrolling is entirely
27050 * "virtual", that is natural browser scrolling of elements is disabled
27051 * (overflow: hidden) and the contents of scrollable elements are wrapped in a
27052 * "scrollerEl"`. Scrolling is simulated by translating the scrollerEl using
27053 * CSS, and {@link Ext.scroll.Indicator scroll indicators} will be shown while
27054 * scrolling since there are no native scrollbars in this mode.
27055 *
27056 * This property is available at application boot time, before document ready.
27057 * @private
27058 */\r
27059 name: 'touchScroll',\r
27060 fn: function() {\r
27061 var touchScroll = 0;\r
27062 if (Ext.os.is.Desktop && (navigator.maxTouchPoints || navigator.msMaxTouchPoints)) {\r
27063 touchScroll = 1;\r
27064 } else if (Ext.supports.Touch) {\r
27065 touchScroll = 2;\r
27066 }\r
27067 return touchScroll;\r
27068 }\r
27069 },\r
27070 {\r
27071 /**
27072 * @property Touch `true` if the browser supports touch input.
27073 *
27074 * This property is available at application boot time, before document ready.
27075 * @type {Boolean}
27076 */\r
27077 name: 'Touch',\r
27078 fn: function() {\r
27079 // IE10 uses a vendor-prefixed maxTouchPoints property\r
27080 var maxTouchPoints = navigator.msMaxTouchPoints || navigator.maxTouchPoints;\r
27081 // if the browser has touch events we can be reasonably sure the device has\r
27082 // a touch screen\r
27083 // browsers that use pointer event have maxTouchPoints > 1 if the\r
27084 // device supports touch input\r
27085 // Chrome Desktop < 39 reports maxTouchPoints === 1 even if there is no\r
27086 // touch support on the device\r
27087 // http://www.w3.org/TR/pointerevents/#widl-Navigator-maxTouchPoints\r
27088 // Chrome Desktop > 39 properly reports maxTouchPoints === 0 and\r
27089 // Chrome Desktop Device Emulation mode reports maxTouchPoints === 1\r
27090 if (Ext.browser.is.Chrome && Ext.browser.version.isLessThanOrEqual(39)) {\r
27091 return (Ext.supports.TouchEvents && maxTouchPoints !== 1) || maxTouchPoints > 1;\r
27092 } else {\r
27093 return Ext.supports.TouchEvents || maxTouchPoints > 0;\r
27094 }\r
27095 }\r
27096 },\r
27097 {\r
27098 /**
27099 * @property TouchEvents `true` if the device supports touch events (`touchstart`,
27100 * `touchmove`, `touchend`).
27101 *
27102 * This property is available at application boot time, before document ready.
27103 * @type {Boolean}
27104 */\r
27105 name: 'TouchEvents',\r
27106 fn: function() {\r
27107 return this.isEventSupported('touchend');\r
27108 }\r
27109 },\r
27110 {\r
27111 name: 'PointerEvents',\r
27112 fn: function() {\r
27113 return navigator.pointerEnabled;\r
27114 }\r
27115 },\r
27116 {\r
27117 name: 'MSPointerEvents',\r
27118 fn: function() {\r
27119 return navigator.msPointerEnabled;\r
27120 }\r
27121 },\r
27122 {\r
27123 /**
27124 * @property Orientation `true` if the device supports different orientations.
27125 * @type {Boolean}
27126 *
27127 * This property is available at application boot time, before document ready.
27128 */\r
27129 name: 'Orientation',\r
27130 fn: function() {\r
27131 return ('orientation' in window) && this.isEventSupported('orientationchange');\r
27132 }\r
27133 },\r
27134 {\r
27135 /**
27136 * @property OrientationChange `true` if the device supports the `orientationchange`
27137 * event.
27138 *
27139 * This property is available at application boot time, before document ready.
27140 * @type {Boolean}
27141 */\r
27142 name: 'OrientationChange',\r
27143 fn: function() {\r
27144 return this.isEventSupported('orientationchange');\r
27145 }\r
27146 },\r
27147 {\r
27148 /**
27149 * @property DeviceMotion `true` if the device supports device motion (acceleration
27150 * and rotation rate).
27151 *
27152 * This property is available at application boot time, before document ready.
27153 * @type {Boolean}
27154 */\r
27155 name: 'DeviceMotion',\r
27156 fn: function() {\r
27157 return this.isEventSupported('devicemotion');\r
27158 }\r
27159 },\r
27160 {\r
27161 /**
27162 * @property Geolocation `true` if the device supports GeoLocation.
27163 * @type {Boolean}
27164 *
27165 * This property is available at application boot time, before document ready.
27166 */\r
27167 /**
27168 * @property GeoLocation `true` if the device supports Geo-location.
27169 * @type {Boolean}
27170 * @deprecated Use `Geolocation` instead (notice the lower-casing of 'L').
27171 */\r
27172 names: [\r
27173 'Geolocation',\r
27174 'GeoLocation'\r
27175 ],\r
27176 fn: function() {\r
27177 return 'geolocation' in window.navigator;\r
27178 }\r
27179 },\r
27180 {\r
27181 name: 'SqlDatabase',\r
27182 fn: function() {\r
27183 return 'openDatabase' in window;\r
27184 }\r
27185 },\r
27186 {\r
27187 name: 'WebSockets',\r
27188 fn: function() {\r
27189 return 'WebSocket' in window;\r
27190 }\r
27191 },\r
27192 {\r
27193 /**
27194 * @property Range `true` if browser support document.createRange native method.
27195 * See https://developer.mozilla.org/en/DOM/range.
27196 *
27197 * This property is available at application boot time, before document ready.
27198 * @type {Boolean}
27199 */\r
27200 name: 'Range',\r
27201 fn: function() {\r
27202 return !!document.createRange;\r
27203 }\r
27204 },\r
27205 {\r
27206 /**
27207 * @property CreateContextualFragment `true` if browser support CreateContextualFragment
27208 * range native methods.
27209 * See https://developer.mozilla.org/en/DOM/range.createContextualFragment
27210 *
27211 * This property is available at application boot time, before document ready.
27212 * @type {Boolean}
27213 */\r
27214 name: 'CreateContextualFragment',\r
27215 fn: function() {\r
27216 var range = !!document.createRange ? document.createRange() : false;\r
27217 return range && !!range.createContextualFragment;\r
27218 }\r
27219 },\r
27220 {\r
27221 /**
27222 * @property History `true` if the device supports HTML5 history. See
27223 * https://developer.mozilla.org/en/DOM/Manipulating_the_browser_history
27224 *
27225 * This property is available at application boot time, before document ready.
27226 * @type {Boolean}
27227 */\r
27228 name: 'History',\r
27229 fn: function() {\r
27230 return ('history' in window && 'pushState' in window.history);\r
27231 }\r
27232 },\r
27233 {\r
27234 /**
27235 * @property Css3DTransforms `true` if the device supports CSS3DTransform.
27236 * @type {Boolean}
27237 *
27238 * This property is available at application boot time, before document ready.
27239 */\r
27240 name: 'Css3dTransforms',\r
27241 fn: function() {\r
27242 // See https://sencha.jira.com/browse/TOUCH-1544\r
27243 return this.has('CssTransforms') && this.isStyleSupported('perspective');\r
27244 }\r
27245 },\r
27246 // TODO - double check vs Ext JS flavor:\r
27247 //return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41'));\r
27248 {\r
27249 // Important that this goes after Css3dTransforms, since tests are run in reverse order\r
27250 name: 'CssTransforms',\r
27251 fn: function() {\r
27252 return this.isStyleSupported('transform');\r
27253 }\r
27254 },\r
27255 {\r
27256 name: 'CssTransformNoPrefix',\r
27257 fn: function() {\r
27258 return this.isStyleSupportedWithoutPrefix('transform');\r
27259 }\r
27260 },\r
27261 {\r
27262 name: 'CssAnimations',\r
27263 fn: function() {\r
27264 return this.isStyleSupported('animationName');\r
27265 }\r
27266 },\r
27267 {\r
27268 /**
27269 * @property Transitions `true` if the device supports CSS3 Transitions.
27270 *
27271 * This property is available at application boot time, before document ready.
27272 * @type {Boolean}
27273 */\r
27274 names: [\r
27275 'CssTransitions',\r
27276 'Transitions'\r
27277 ],\r
27278 fn: function() {\r
27279 return this.isStyleSupported('transitionProperty');\r
27280 }\r
27281 },\r
27282 {\r
27283 /**
27284 * @property Audio `true` if the device supports the HTML5 `audio` tag.
27285 *
27286 * This property is available at application boot time, before document ready.
27287 * @type {Boolean}
27288 */\r
27289 /**
27290 * @property AudioTag `true` if the device supports the HTML5 `audio` tag.
27291 * @type {Boolean}
27292 * @deprecated Use `Audio` instead.
27293 */\r
27294 names: [\r
27295 'Audio',\r
27296 'AudioTag'\r
27297 ],\r
27298 fn: function() {\r
27299 return !!this.getTestElement('audio').canPlayType;\r
27300 }\r
27301 },\r
27302 {\r
27303 /**
27304 * @property Video `true` if the device supports the HTML5 `video` tag.
27305 *
27306 * This property is available at application boot time, before document ready.
27307 * @type {Boolean}
27308 */\r
27309 name: 'Video',\r
27310 fn: function() {\r
27311 return !!this.getTestElement('video').canPlayType;\r
27312 }\r
27313 },\r
27314 {\r
27315 /**
27316 * @property LocalStorage `true` if localStorage is supported.
27317 *
27318 * This property is available at application boot time, before document ready.
27319 * @type {Boolean}
27320 */\r
27321 name: 'LocalStorage',\r
27322 fn: function() {\r
27323 try {\r
27324 // IE10/Win8 throws "Access Denied" accessing window.localStorage, so\r
27325 // this test needs to have a try/catch\r
27326 if ('localStorage' in window && window['localStorage'] !== null) {\r
27327 // jshint ignore:line\r
27328 //this should throw an error in private browsing mode in iOS as well\r
27329 localStorage.setItem('sencha-localstorage-test', 'test success');\r
27330 //clean up if setItem worked\r
27331 localStorage.removeItem('sencha-localstorage-test');\r
27332 return true;\r
27333 }\r
27334 } catch (e) {}\r
27335 // ignore\r
27336 return false;\r
27337 }\r
27338 },\r
27339 {\r
27340 /**
27341 * @property XHR2 `true` if the browser supports XMLHttpRequest
27342 *
27343 * This property is available at application boot time, before document ready.
27344 * @type {Boolean}
27345 */\r
27346 name: 'XHR2',\r
27347 fn: function() {\r
27348 return window.ProgressEvent && window.FormData && window.XMLHttpRequest && ('withCredentials' in new XMLHttpRequest());\r
27349 }\r
27350 },\r
27351 {\r
27352 /**
27353 * @property XHRUploadProgress `true` if the browser supports XMLHttpRequest
27354 * upload progress info
27355 *
27356 * This property is available at application boot time, before document ready.
27357 * @type {Boolean}
27358 */\r
27359 name: 'XHRUploadProgress',\r
27360 fn: function() {\r
27361 if (window.XMLHttpRequest && !Ext.browser.is.AndroidStock) {\r
27362 var xhr = new XMLHttpRequest();\r
27363 return xhr && ('upload' in xhr) && ('onprogress' in xhr.upload);\r
27364 }\r
27365 return false;\r
27366 }\r
27367 },\r
27368 {\r
27369 /**
27370 * @property NumericInputPlaceHolder `true` if the browser supports placeholders
27371 * on numeric input fields
27372 *
27373 * This property is available at application boot time, before document ready.
27374 * @type {Boolean}
27375 */\r
27376 name: 'NumericInputPlaceHolder',\r
27377 fn: function() {\r
27378 return !(Ext.browser.is.AndroidStock4 && Ext.os.version.getMinor() < 2);\r
27379 }\r
27380 },\r
27381 /**
27382 * @property {String} matchesSelector
27383 * The method name which matches an element against a selector if implemented in this environment.
27384 *
27385 * This property is available at application boot time, before document ready.
27386 */\r
27387 {\r
27388 name: 'matchesSelector',\r
27389 fn: function() {\r
27390 var el = document.documentElement,\r
27391 w3 = 'matches',\r
27392 wk = 'webkitMatchesSelector',\r
27393 ms = 'msMatchesSelector',\r
27394 mz = 'mozMatchesSelector';\r
27395 return el[w3] ? w3 : el[wk] ? wk : el[ms] ? ms : el[mz] ? mz : null;\r
27396 }\r
27397 },\r
27398 /**
27399 * @property RightMargin `true` if the device supports right margin.
27400 * See https://bugs.webkit.org/show_bug.cgi?id=13343 for why this is needed.
27401 *
27402 * This property is *NOT* available at application boot time. Only after the document ready event.
27403 * @type {Boolean}
27404 */\r
27405 {\r
27406 name: 'RightMargin',\r
27407 ready: true,\r
27408 fn: function(doc, div) {\r
27409 var view = doc.defaultView;\r
27410 return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight !== '0px');\r
27411 }\r
27412 },\r
27413 /**
27414 * @property DisplayChangeInputSelectionBug `true` if INPUT elements lose their
27415 * selection when their display style is changed. Essentially, if a text input
27416 * has focus and its display style is changed, the I-beam disappears.
27417 *
27418 * This bug is encountered due to the work around in place for the {@link #RightMargin}
27419 * bug. This has been observed in Safari 4.0.4 and older, and appears to be fixed
27420 * in Safari 5. It's not clear if Safari 4.1 has the bug, but it has the same WebKit
27421 * version number as Safari 5 (according to http://unixpapa.com/js/gecko.html).
27422 *
27423 * This property is available at application boot time, before document ready.
27424 */\r
27425 {\r
27426 name: 'DisplayChangeInputSelectionBug',\r
27427 fn: function() {\r
27428 var webKitVersion = Ext.webKitVersion;\r
27429 // WebKit but older than Safari 5 or Chrome 6:\r
27430 return 0 < webKitVersion && webKitVersion < 533;\r
27431 }\r
27432 },\r
27433 /**
27434 * @property DisplayChangeTextAreaSelectionBug `true` if TEXTAREA elements lose their
27435 * selection when their display style is changed. Essentially, if a text area has
27436 * focus and its display style is changed, the I-beam disappears.
27437 *
27438 * This bug is encountered due to the work around in place for the {@link #RightMargin}
27439 * bug. This has been observed in Chrome 10 and Safari 5 and older, and appears to
27440 * be fixed in Chrome 11.
27441 *
27442 * This property is available at application boot time, before document ready.
27443 */\r
27444 {\r
27445 name: 'DisplayChangeTextAreaSelectionBug',\r
27446 fn: function() {\r
27447 var webKitVersion = Ext.webKitVersion;\r
27448 /*
27449 Has bug w/textarea:
27450
27451 (Chrome) Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US)
27452 AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.127
27453 Safari/534.16
27454 (Safari) Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-us)
27455 AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5
27456 Safari/533.21.1
27457
27458 No bug:
27459
27460 (Chrome) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7)
27461 AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.57
27462 Safari/534.24
27463 */\r
27464 return 0 < webKitVersion && webKitVersion < 534.24;\r
27465 }\r
27466 },\r
27467 /**
27468 * @property TransparentColor `true` if the device supports transparent color.
27469 * @type {Boolean}
27470 *
27471 * This property is *NOT* available at application boot time. Only after the document ready event.
27472 */\r
27473 {\r
27474 name: 'TransparentColor',\r
27475 ready: true,\r
27476 fn: function(doc, div, view) {\r
27477 view = doc.defaultView;\r
27478 return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor !== 'transparent');\r
27479 }\r
27480 },\r
27481 /**
27482 * @property ComputedStyle `true` if the browser supports document.defaultView.getComputedStyle().
27483 * @type {Boolean}
27484 *
27485 * This property is *NOT* available at application boot time. Only after the document ready event.
27486 */\r
27487 {\r
27488 name: 'ComputedStyle',\r
27489 ready: true,\r
27490 fn: function(doc, div, view) {\r
27491 view = doc.defaultView;\r
27492 return view && view.getComputedStyle;\r
27493 }\r
27494 },\r
27495 /**
27496 * @property Float `true` if the device supports CSS float.
27497 * @type {Boolean}
27498 *
27499 * This property is available at application boot time, before document ready.
27500 */\r
27501 {\r
27502 name: 'Float',\r
27503 fn: function(doc) {\r
27504 return 'cssFloat' in doc.documentElement.style;\r
27505 }\r
27506 },\r
27507 /**
27508 * @property CSS3BorderRadius `true` if the device supports CSS3 border radius.
27509 * @type {Boolean}
27510 *
27511 * This property is *NOT* available at application boot time. Only after the document ready event.
27512 */\r
27513 {\r
27514 name: 'CSS3BorderRadius',\r
27515 ready: true,\r
27516 fn: function(doc) {\r
27517 var domPrefixes = [\r
27518 'borderRadius',\r
27519 'BorderRadius',\r
27520 'MozBorderRadius',\r
27521 'WebkitBorderRadius',\r
27522 'OBorderRadius',\r
27523 'KhtmlBorderRadius'\r
27524 ],\r
27525 pass = false,\r
27526 i;\r
27527 for (i = 0; i < domPrefixes.length; i++) {\r
27528 if (doc.documentElement.style[domPrefixes[i]] !== undefined) {\r
27529 pass = true;\r
27530 }\r
27531 }\r
27532 return pass && !Ext.isIE9;\r
27533 }\r
27534 },\r
27535 /**
27536 * @property CSS3LinearGradient `true` if the device supports CSS3 linear gradients.
27537 * @type {Boolean}
27538 *
27539 * This property is available at application boot time, before document ready.
27540 */\r
27541 {\r
27542 name: 'CSS3LinearGradient',\r
27543 fn: function(doc, div) {\r
27544 var property = 'background-image:',\r
27545 webkit = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))',\r
27546 w3c = 'linear-gradient(left top, black, white)',\r
27547 moz = '-moz-' + w3c,\r
27548 ms = '-ms-' + w3c,\r
27549 opera = '-o-' + w3c,\r
27550 options = [\r
27551 property + webkit,\r
27552 property + w3c,\r
27553 property + moz,\r
27554 property + ms,\r
27555 property + opera\r
27556 ];\r
27557 div.style.cssText = options.join(';');\r
27558 return (("" + div.style.backgroundImage).indexOf('gradient') !== -1) && !Ext.isIE9;\r
27559 }\r
27560 },\r
27561 /**
27562 * @property MouseEnterLeave `true` if the browser supports mouseenter and mouseleave events
27563 * @type {Boolean}
27564 *
27565 * This property is available at application boot time, before document ready.
27566 */\r
27567 {\r
27568 name: 'MouseEnterLeave',\r
27569 fn: function(doc) {\r
27570 return ('onmouseenter' in doc.documentElement && 'onmouseleave' in doc.documentElement);\r
27571 }\r
27572 },\r
27573 /**
27574 * @property MouseWheel `true` if the browser supports the mousewheel event
27575 * @type {Boolean}
27576 *
27577 * This property is available at application boot time, before document ready.
27578 */\r
27579 {\r
27580 name: 'MouseWheel',\r
27581 fn: function(doc) {\r
27582 return ('onmousewheel' in doc.documentElement);\r
27583 }\r
27584 },\r
27585 /**
27586 * @property Opacity `true` if the browser supports normal css opacity
27587 * @type {Boolean}
27588 *
27589 * This property is available at application boot time, before document ready.
27590 */\r
27591 {\r
27592 name: 'Opacity',\r
27593 fn: function(doc, div) {\r
27594 // Not a strict equal comparison in case opacity can be converted to a number.\r
27595 if (Ext.isIE8) {\r
27596 return false;\r
27597 }\r
27598 div.firstChild.style.cssText = 'opacity:0.73';\r
27599 return div.firstChild.style.opacity == '0.73';\r
27600 }\r
27601 },\r
27602 // jshint ignore:line\r
27603 /**
27604 * @property Placeholder `true` if the browser supports the HTML5 placeholder attribute on inputs
27605 * @type {Boolean}
27606 *
27607 * This property is available at application boot time, before document ready.
27608 */\r
27609 {\r
27610 name: 'Placeholder',\r
27611 fn: function(doc) {\r
27612 return 'placeholder' in doc.createElement('input');\r
27613 }\r
27614 },\r
27615 /**
27616 * @property Direct2DBug `true` if when asking for an element's dimension via offsetWidth or offsetHeight,
27617 * getBoundingClientRect, etc. the browser returns the subpixel width rounded to the nearest pixel.
27618 *
27619 * This property is available at application boot time, before document ready.
27620 * @type {Boolean}
27621 */\r
27622 {\r
27623 name: 'Direct2DBug',\r
27624 fn: function(doc) {\r
27625 return Ext.isString(doc.documentElement.style.msTransformOrigin) && Ext.isIE9m;\r
27626 }\r
27627 },\r
27628 /**
27629 * @property BoundingClientRect `true` if the browser supports the getBoundingClientRect method on elements
27630 * @type {Boolean}
27631 *
27632 * This property is available at application boot time, before document ready.
27633 */\r
27634 {\r
27635 name: 'BoundingClientRect',\r
27636 fn: function(doc) {\r
27637 return 'getBoundingClientRect' in doc.documentElement;\r
27638 }\r
27639 },\r
27640 /**
27641 * @property RotatedBoundingClientRect `true` if the BoundingClientRect is
27642 * rotated when the element is rotated using a CSS transform.
27643 * @type {Boolean}
27644 *
27645 * This property is *NOT* available at application boot time. Only after the document ready event.
27646 */\r
27647 {\r
27648 name: 'RotatedBoundingClientRect',\r
27649 ready: true,\r
27650 fn: function(doc) {\r
27651 var body = doc.body,\r
27652 supports = false,\r
27653 el = doc.createElement('div'),\r
27654 style = el.style;\r
27655 if (el.getBoundingClientRect) {\r
27656 // If the document body already has child nodes (text nodes etc) we can end\r
27657 // up with subpixel rounding errors in IE11 when measuring the height.\r
27658 // Absolute positioning prevents this.\r
27659 style.position = 'absolute';\r
27660 style.top = "0";\r
27661 style.WebkitTransform = style.MozTransform = style.msTransform = style.OTransform = style.transform = 'rotate(90deg)';\r
27662 style.width = '100px';\r
27663 style.height = '30px';\r
27664 body.appendChild(el);\r
27665 supports = el.getBoundingClientRect().height !== 100;\r
27666 body.removeChild(el);\r
27667 }\r
27668 return supports;\r
27669 }\r
27670 },\r
27671 /**
27672 * @property ChildContentClearedWhenSettingInnerHTML `true` if created child elements
27673 * lose their innerHTML when modifying the innerHTML of the parent element.
27674 * @type {Boolean}
27675 *
27676 * This property is *NOT* available at application boot time. Only after the document ready event.
27677 */\r
27678 {\r
27679 name: 'ChildContentClearedWhenSettingInnerHTML',\r
27680 ready: true,\r
27681 fn: function() {\r
27682 var el = this.getTestElement(),\r
27683 child;\r
27684 el.innerHTML = '<div>a</div>';\r
27685 child = el.firstChild;\r
27686 el.innerHTML = '<div>b</div>';\r
27687 return child.innerHTML !== 'a';\r
27688 }\r
27689 },\r
27690 {\r
27691 name: 'IncludePaddingInWidthCalculation',\r
27692 ready: true,\r
27693 fn: function(doc, div) {\r
27694 return div.childNodes[1].firstChild.offsetWidth === 210;\r
27695 }\r
27696 },\r
27697 {\r
27698 name: 'IncludePaddingInHeightCalculation',\r
27699 ready: true,\r
27700 fn: function(doc, div) {\r
27701 return div.childNodes[1].firstChild.offsetHeight === 210;\r
27702 }\r
27703 },\r
27704 /**
27705 * @property TextAreaMaxLength `true` if the browser supports maxlength on textareas.
27706 * @type {Boolean}
27707 *
27708 * This property is available at application boot time, before document ready.
27709 */\r
27710 {\r
27711 name: 'TextAreaMaxLength',\r
27712 fn: function(doc) {\r
27713 return ('maxlength' in doc.createElement('textarea'));\r
27714 }\r
27715 },\r
27716 /**
27717 * @property GetPositionPercentage `true` if the browser will return the left/top/right/bottom
27718 * position as a percentage when explicitly set as a percentage value.
27719 *
27720 * This property is *NOT* available at application boot time. Only after the document ready event.
27721 * @type {Boolean}
27722 */\r
27723 // Related bug: https://bugzilla.mozilla.org/show_bug.cgi?id=707691#c7\r
27724 {\r
27725 name: 'GetPositionPercentage',\r
27726 ready: true,\r
27727 fn: function(doc, div) {\r
27728 return Ext.feature.getStyle(div.childNodes[2], 'left') === '10%';\r
27729 }\r
27730 },\r
27731 /**
27732 * @property {Boolean} PercentageHeightOverflowBug
27733 * In some browsers (IE quirks, IE6, IE7, IE9, chrome, safari and opera at the time
27734 * of this writing) a percentage-height element ignores the horizontal scrollbar
27735 * of its parent element. This method returns true if the browser is affected
27736 * by this bug.
27737 *
27738 * This property is *NOT* available at application boot time. Only after the document ready event.
27739 * @private
27740 */\r
27741 {\r
27742 name: 'PercentageHeightOverflowBug',\r
27743 ready: true,\r
27744 fn: function(doc) {\r
27745 var hasBug = false,\r
27746 style, el;\r
27747 if (Ext.getScrollbarSize().height) {\r
27748 // must have space-consuming scrollbars for bug to be possible\r
27749 el = this.getTestElement();\r
27750 style = el.style;\r
27751 style.height = '50px';\r
27752 style.width = '50px';\r
27753 style.overflow = 'auto';\r
27754 style.position = 'absolute';\r
27755 el.innerHTML = [\r
27756 '<div style="display:table;height:100%;">',\r
27757 // The element that causes the horizontal overflow must be \r
27758 // a child of the element with the 100% height, otherwise\r
27759 // horizontal overflow is not triggered in webkit quirks mode\r
27760 '<div style="width:51px;"></div>',\r
27761 '</div>'\r
27762 ].join('');\r
27763 doc.body.appendChild(el);\r
27764 if (el.firstChild.offsetHeight === 50) {\r
27765 hasBug = true;\r
27766 }\r
27767 doc.body.removeChild(el);\r
27768 }\r
27769 return hasBug;\r
27770 }\r
27771 },\r
27772 /**
27773 * @property {Boolean} xOriginBug
27774 * In Chrome 24.0, an RTL element which has vertical overflow positions its right X origin incorrectly.
27775 * It skips a non-existent scrollbar which has been moved to the left edge due to the RTL setting.
27776 *
27777 * http://code.google.com/p/chromium/issues/detail?id=174656
27778 *
27779 * This method returns true if the browser is affected by this bug.
27780 *
27781 * This property is *NOT* available at application boot time. Only after the document ready event.
27782 * @private
27783 */\r
27784 {\r
27785 name: 'xOriginBug',\r
27786 ready: true,\r
27787 fn: function(doc, div) {\r
27788 div.innerHTML = '<div id="b1" style="height:100px;width:100px;direction:rtl;position:relative;overflow:scroll">' + '<div id="b2" style="position:relative;width:100%;height:20px;"></div>' + '<div id="b3" style="position:absolute;width:20px;height:20px;top:0px;right:0px"></div>' + '</div>';\r
27789 var outerBox = document.getElementById('b1').getBoundingClientRect(),\r
27790 b2 = document.getElementById('b2').getBoundingClientRect(),\r
27791 b3 = document.getElementById('b3').getBoundingClientRect();\r
27792 return (b2.left !== outerBox.left && b3.right !== outerBox.right);\r
27793 }\r
27794 },\r
27795 /**
27796 * @property {Boolean} ScrollWidthInlinePaddingBug
27797 * In some browsers the right padding of an overflowing element is not accounted
27798 * for in its scrollWidth. The result can vary depending on whether or not
27799 * The element contains block-level children. This method tests the effect
27800 * of padding on scrollWidth when there are no block-level children inside the
27801 * overflowing element.
27802 *
27803 * This method returns true if the browser is affected by this bug.
27804 *
27805 * This property is *NOT* available at application boot time. Only after the document ready event.
27806 */\r
27807 {\r
27808 name: 'ScrollWidthInlinePaddingBug',\r
27809 ready: true,\r
27810 fn: function(doc) {\r
27811 var hasBug = false,\r
27812 style, el;\r
27813 el = doc.createElement('div');\r
27814 style = el.style;\r
27815 style.height = '50px';\r
27816 style.width = '50px';\r
27817 style.padding = '10px';\r
27818 style.overflow = 'hidden';\r
27819 style.position = 'absolute';\r
27820 el.innerHTML = '<span style="display:inline-block;zoom:1;height:60px;width:60px;"></span>';\r
27821 doc.body.appendChild(el);\r
27822 if (el.scrollWidth === 70) {\r
27823 hasBug = true;\r
27824 }\r
27825 doc.body.removeChild(el);\r
27826 return hasBug;\r
27827 }\r
27828 },\r
27829 /**
27830 * @property {Boolean} rtlVertScrollbarOnRight
27831 * Safari, in RTL mode keeps the scrollbar at the right side.
27832 * This means that when two elements must keep their left/right positions synched, if one has no vert
27833 * scrollbar, it must have some extra padding.
27834 * See https://sencha.jira.com/browse/EXTJSIV-11245
27835 *
27836 * This property is *NOT* available at application boot time. Only after the document ready event.
27837 * @private
27838 */\r
27839 {\r
27840 name: 'rtlVertScrollbarOnRight',\r
27841 ready: true,\r
27842 fn: function(doc, div) {\r
27843 div.innerHTML = '<div style="height:100px;width:100px;direction:rtl;overflow:scroll">' + '<div style="width:20px;height:200px;"></div>' + '</div>';\r
27844 var outerBox = div.firstChild,\r
27845 innerBox = outerBox.firstChild;\r
27846 return (innerBox.offsetLeft + innerBox.offsetWidth !== outerBox.offsetLeft + outerBox.offsetWidth);\r
27847 }\r
27848 },\r
27849 /**
27850 * @property {Boolean} rtlVertScrollbarOverflowBug
27851 * In Chrome, in RTL mode, horizontal overflow only into the vertical scrollbar does NOT trigger horizontal scrollability.
27852 * See https://code.google.com/p/chromium/issues/detail?id=179332
27853 * We need to detect this for when a grid header needs to have exactly the same horizontal scrolling range as its table view.
27854 * See {@link Ext.grid.ColumnLayout#publishInnerCtSize}
27855 * TODO: Remove this when all supported Chrome versions are fixed.
27856 *
27857 * This property is *NOT* available at application boot time. Only after the document ready event.
27858 * @private
27859 */\r
27860 {\r
27861 name: 'rtlVertScrollbarOverflowBug',\r
27862 ready: true,\r
27863 fn: function(doc, div) {\r
27864 div.innerHTML = '<div style="height:100px;width:100px;direction:rtl;overflow:auto">' + '<div style="width:95px;height:200px;"></div>' + '</div>';\r
27865 // If the bug is present, the 95 pixel wide inner div, encroaches into the\r
27866 // vertical scrollbar, but does NOT trigger horizontal overflow, so the clientHeight remains\r
27867 // equal to the offset height.\r
27868 var outerBox = div.firstChild;\r
27869 return outerBox.clientHeight === outerBox.offsetHeight;\r
27870 }\r
27871 },\r
27872 {\r
27873 identity: 'defineProperty',\r
27874 fn: function() {\r
27875 if (Ext.isIE8m) {\r
27876 Ext.Object.defineProperty = Ext.emptyFn;\r
27877 return false;\r
27878 }\r
27879 return true;\r
27880 }\r
27881 },\r
27882 {\r
27883 identify: 'nativeXhr',\r
27884 fn: function() {\r
27885 if (typeof XMLHttpRequest !== 'undefined') {\r
27886 return true;\r
27887 }\r
27888 // Apply a polyfill:\r
27889 XMLHttpRequest = function() {\r
27890 // jshint ignore:line\r
27891 try {\r
27892 return new ActiveXObject('MSXML2.XMLHTTP.3.0');\r
27893 } // jshint ignore:line\r
27894 catch (ex) {\r
27895 return null;\r
27896 }\r
27897 };\r
27898 return false;\r
27899 }\r
27900 },\r
27901 /**
27902 * @property {Boolean} SpecialKeyDownRepeat
27903 * True if the browser fires the keydown event on specialkey autorepeat
27904 *
27905 * note 1: IE fires ONLY the keydown event on specialkey autorepeat
27906 * note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on
27907 * specialkey autorepeat (research done by Jan Wolter at
27908 * http://unixpapa.com/js/key.html)
27909 * note 3: Opera 12 behaves like other modern browsers so this workaround does not
27910 * work anymore
27911 *
27912 * This property is available at application boot time, before document ready.
27913 */\r
27914 {\r
27915 name: 'SpecialKeyDownRepeat',\r
27916 fn: function() {\r
27917 return Ext.isWebKit ? parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 : !((Ext.isGecko && !Ext.isWindows) || (Ext.isOpera && Ext.operaVersion < 12));\r
27918 }\r
27919 },\r
27920 /**
27921 * @property {Boolean} EmulatedMouseOver
27922 * True if the browser emulates a mouseover event on tap (mobile safari)
27923 *
27924 * This property is available at application boot time, before document ready.
27925 */\r
27926 {\r
27927 name: 'EmulatedMouseOver',\r
27928 fn: function() {\r
27929 // TODO: is it possible to feature detect this?\r
27930 return Ext.os.is.iOS;\r
27931 }\r
27932 },\r
27933 /**
27934 * @property Hashchange True if the user agent supports the hashchange event
27935 *
27936 * This property is available at application boot time, before document ready.
27937 * @type {Boolean}
27938 */\r
27939 {\r
27940 // support Vector 12\r
27941 name: 'Hashchange',\r
27942 fn: function() {\r
27943 // Note that IE8 in IE7 compatibility mode reports true for 'onhashchange' in window, so also test documentMode\r
27944 var docMode = document.documentMode;\r
27945 return 'onhashchange' in window && (docMode === undefined || docMode > 7);\r
27946 }\r
27947 },\r
27948 /**
27949 * @property FixedTableWidthBug
27950 * @private
27951 * @type {Boolean}
27952 * `true` if the browser has this bug: https://bugs.webkit.org/show_bug.cgi?id=130239
27953 *
27954 * This property is *NOT* available at application boot time. Only after the document ready event.
27955 */\r
27956 {\r
27957 name: 'FixedTableWidthBug',\r
27958 ready: true,\r
27959 fn: function() {\r
27960 if (Ext.isIE8) {\r
27961 // IE8 incorrectly detects that we have this bug.\r
27962 return false;\r
27963 }\r
27964 var outer = document.createElement('div'),\r
27965 inner = document.createElement('div'),\r
27966 width;\r
27967 outer.setAttribute('style', 'display:table;table-layout:fixed;');\r
27968 inner.setAttribute('style', 'display:table-cell;min-width:50px;');\r
27969 outer.appendChild(inner);\r
27970 document.body.appendChild(outer);\r
27971 // must poke offsetWidth to trigger a reflow before setting width\r
27972 outer.offsetWidth;\r
27973 // jshint ignore:line\r
27974 outer.style.width = '25px';\r
27975 width = outer.offsetWidth;\r
27976 document.body.removeChild(outer);\r
27977 return width === 50;\r
27978 }\r
27979 },\r
27980 /**
27981 * @property FocusinFocusoutEvents
27982 * @private
27983 * @type {Boolean}
27984 * `true` if the browser supports focusin and focusout events:
27985 * https://developer.mozilla.org/en-US/docs/Web/Events/focusin
27986 * At this point, only Firefox does not, see this bug:
27987 * https://bugzilla.mozilla.org/show_bug.cgi?id=687787
27988 *
27989 * This property is available at application boot time, before document ready.
27990 */\r
27991 {\r
27992 name: 'FocusinFocusoutEvents',\r
27993 fn: function() {\r
27994 // There is no reliable way to feature detect focusin/focusout event support.\r
27995 // window.onfocusin will return undefined both in Chrome (where it is supported)\r
27996 // and in Firefox (where it is not supported); adding an element and trying to\r
27997 // focus it will fail when the browser window itself is not focused.\r
27998 return !Ext.isGecko;\r
27999 }\r
28000 },\r
28001 /**
28002 * @property {Boolean} AsyncFocusEvents
28003 * `true` if the browser fires focus events (focus, blur, focusin, focusout)
28004 * asynchronously, i.e. in a separate event loop invocation. This is only true
28005 * for all versions Internet Explorer; Microsoft Edge and other browsers fire
28006 * focus events synchronously.
28007 */\r
28008 {\r
28009 name: 'AsyncFocusEvents',\r
28010 fn: function() {\r
28011 // The sad part is that we can't feature detect this because the focus\r
28012 // event won't be fired when the browser window itself is not focused.\r
28013 // Private shortcut for brevity\r
28014 return Ext.asyncFocus = !!Ext.isIE;\r
28015 }\r
28016 },\r
28017 /**
28018 * @property {Boolean} HighContrastMode `true` if the browser is currently
28019 * running in Windows High Contrast accessibility mode.
28020 *
28021 * @property {Object} accessibility Accessibility features.
28022 *
28023 * @property {Boolean} accessibility.Images `true` if the browser is configured
28024 * to display images.
28025 *
28026 * @property {Boolean} accessibility.BackgroundImages `true` if the browser
28027 * is configured to display background images.
28028 *
28029 * @property {Boolean} accessibility.BorderColors `true` if the browser
28030 * is configured to honor CSS styling for border colors.
28031 *
28032 * @property {Boolean} accessibility.LightOnDark `true` if the browser
28033 * is currently using reverse colors in light-on-dark accessibility mode.
28034 */\r
28035 {\r
28036 name: 'accessibility',\r
28037 ready: true,\r
28038 fn: function(doc) {\r
28039 var body = doc.body,\r
28040 div, img, style, supports, bgImg;\r
28041 function getColor(colorTxt) {\r
28042 var values = [],\r
28043 colorValue = 0,\r
28044 regex, match;\r
28045 if (colorTxt.indexOf('rgb(') !== -1) {\r
28046 values = colorTxt.replace('rgb(', '').replace(')', '').split(', ');\r
28047 } else if (colorTxt.indexOf('#') !== -1) {\r
28048 regex = colorTxt.length === 7 ? /^#(\S\S)(\S\S)(\S\S)$/ : /^#(\S)(\S)(\S)$/;\r
28049 match = colorTxt.match(regex);\r
28050 if (match) {\r
28051 values = [\r
28052 '0x' + match[1],\r
28053 '0x' + match[2],\r
28054 '0x' + match[3]\r
28055 ];\r
28056 }\r
28057 }\r
28058 for (var i = 0; i < values.length; i++) {\r
28059 colorValue += parseInt(values[i]);\r
28060 }\r
28061 return colorValue;\r
28062 }\r
28063 div = doc.createElement('div');\r
28064 img = doc.createElement('img');\r
28065 style = div.style;\r
28066 Ext.apply(style, {\r
28067 width: '2px',\r
28068 position: 'absolute',\r
28069 clip: 'rect(1px,1px,1px,1px)',\r
28070 borderWidth: '1px',\r
28071 borderStyle: 'solid',\r
28072 borderTopTolor: '#f00',\r
28073 borderRightColor: '#ff0',\r
28074 backgroundColor: '#fff',\r
28075 backgroundImage: 'url(' + Ext.BLANK_IMAGE_URL + ')'\r
28076 });\r
28077 img.alt = '';\r
28078 img.src = Ext.BLANK_IMAGE_URL;\r
28079 div.appendChild(img);\r
28080 body.appendChild(div);\r
28081 // Now check if the styles were indeed honored\r
28082 style = div.currentStyle || div.style;\r
28083 bgImg = style.backgroundImage;\r
28084 supports = {\r
28085 // In IE it is possible to untick "Show pictures" option in Advanced\r
28086 // settings; this will result in img element reporting its readyState\r
28087 // as 'uninitialized'.\r
28088 // See http://www.paciellogroup.com/blog/2011/10/detecting-if-images-are-disabled-in-browsers/\r
28089 Images: img.offsetWidth === 1 && img.readyState !== 'uninitialized',\r
28090 BackgroundImages: !(bgImg !== null && (bgImg === "none" || bgImg === "url(invalid-url:)")),\r
28091 BorderColors: style.borderTopColor !== style.borderRightColor,\r
28092 LightOnDark: getColor(style.color) - getColor(style.backgroundColor) > 0\r
28093 };\r
28094 Ext.supports.HighContrastMode = !supports.BackgroundImages;\r
28095 body.removeChild(div);\r
28096 div = img = null;\r
28097 return supports;\r
28098 }\r
28099 },\r
28100 0\r
28101 ]\r
28102};\r
28103// placeholder so legacy browser detectors can come/go cleanly\r
28104Ext.feature.tests.pop();\r
28105// remove the placeholder\r
28106Ext.supports = {};\r
28107Ext.feature.detect();\r
28108\r
28109/**
28110 * This class manages ready detection and handling. Direct use of this class is not
28111 * recommended. Instead use `Ext.onReady`:
28112 *
28113 * Ext.onReady(function () {
28114 * // DOM and Framework are ready...
28115 * });
28116 *
28117 * ## DOM Ready
28118 *
28119 * The lowest-level of readiness is DOM readiness. This level implies only that the document
28120 * body exists. Many things require the DOM to be ready for manipulation. If that is all
28121 * that is required, the `Ext.onDocumentReady` method can be called to register a callback
28122 * to be called as soon as the DOM is ready:
28123 *
28124 * Ext.onDocumentReady(function () {
28125 * // the document body is ready
28126 * });
28127 *
28128 * ## Framework Ready
28129 *
28130 * In production builds of applications it is common to have all of the code loaded before
28131 * DOM ready, so the need to wait for "onReady" is often confused with only that concern.
28132 * This is easy to understand, at least in part because historically `Ext.onReady` only
28133 * waited for DOM ready.
28134 *
28135 * With the introduction of `Ext.Loader`, however, it became common for DOM ready to occur
28136 * in the middle of dynamically loading code. If application code were executed at that
28137 * time, any use of the yet-to-be-loaded classes would throw errors. As a consequence of
28138 * this, the `Ext.onReady` mechanism was extended to wait for both DOM ready *and* all of
28139 * the required classes to be loaded.
28140 *
28141 * When the framework enters or leaves a state where it is not ready (for example, the
28142 * first dynamic load is requested or last load completes), `Ext.env.Ready` is informed.
28143 * For example:
28144 *
28145 * Ext.env.Ready.block();
28146 *
28147 * //...
28148 *
28149 * Ext.env.Ready.unblock();
28150 *
28151 * When there are no blocks and the DOM is ready, the Framework is ready and the "onReady"
28152 * callbacks are called.
28153 *
28154 * Priority can be used to control the ordering of onReady listeners, for example:
28155 *
28156 * Ext.onReady(function() {
28157 *
28158 * }, null, {
28159 * priority: 100
28160 * });
28161 *
28162 * Ready listeners with higher priorities will run sooner than those with lower priorities,
28163 * the default priority being `0`. Internally the framework reserves priorities of 1000
28164 * or greater, and -1000 or lesser for onReady handlers that must run before or after
28165 * any application code. Applications should stick to using priorities in the -999 - 999
28166 * range. The following priorities are currently in use by the framework:
28167 *
28168 * - Element_scroll rtl override: `1001`
28169 * - Event system initialization: `2000`
28170 * - Ext.dom.Element: `1500`
28171 *
28172 * @class Ext.env.Ready
28173 * @singleton
28174 * @private
28175 * @since 5.0.0
28176 */\r
28177Ext.env.Ready = {\r
28178 // @define Ext.env.Ready\r
28179 // @require Ext.env.Browser\r
28180 // @require Ext.env.OS\r
28181 // @require Ext.env.Feature\r
28182 /**
28183 * @property {Number} blocks The number of Framework readiness blocks.
28184 * @private
28185 */\r
28186 blocks: (location.search || '').indexOf('ext-pauseReadyFire') > 0 ? 1 : 0,\r
28187 /**
28188 * @property {Number} bound This property stores the state of event listeners bound
28189 * to the document or window to detect ready state.
28190 * @private
28191 */\r
28192 bound: 0,\r
28193 /**
28194 * @property {Number} [delay=1]
28195 * This allows the DOM listener thread to complete (usually desirable with mobWebkit,
28196 * Gecko) before firing the entire onReady chain (high stack load on Loader). For mobile
28197 * devices when running from Home Screen, the splash screen will not disappear until
28198 * all external resource requests finish. This delay clears the splash screen.
28199 * @private
28200 */\r
28201 delay: 1,\r
28202 /**
28203 * @property {Event[]} events An array of events that have triggered ready state. This
28204 * is for diagnostic purposes only and is only available in debug builds.
28205 * An array
28206 * @private
28207 */\r
28208 events: [],\r
28209 /**
28210 * @property {Boolean} firing This property is `true` when we currently calling the
28211 * listeners.
28212 * @private
28213 */\r
28214 firing: false,\r
28215 /**
28216 * @property {Number} generation A counter of the number of mutations of `listeners`.
28217 * @private
28218 */\r
28219 generation: 0,\r
28220 /**
28221 * @property {Object[]} listeners The set of listeners waiting for ready.
28222 * @private
28223 */\r
28224 listeners: [],\r
28225 /**
28226 * @property {Number} nextId A counter so we can assign listeners an `id` to keep
28227 * them in FIFO order.
28228 * @private
28229 */\r
28230 nextId: 0,\r
28231 /**
28232 * @property {Number} sortGeneration A captured value of `generation` that indicates
28233 * when the `listeners` were last sorted.
28234 * @private
28235 */\r
28236 sortGeneration: 0,\r
28237 /**
28238 * @property {Number} state
28239 * Holds the current ready state as managed by this class. The values possible are:
28240 *
28241 * * 0 - Not ready.
28242 * * 1 - Ready detected but listeners are not yet notified.
28243 * * 2 - Ready detected and listeners are notified. See also `firing`.
28244 *
28245 * @private
28246 */\r
28247 state: 0,\r
28248 /**
28249 * @property {Object} timer The handle from `setTimeout` for the delayed notification
28250 * of ready.
28251 * @private
28252 */\r
28253 timer: null,\r
28254 /**
28255 * Binds the appropriate browser event for checking if the DOM has loaded.
28256 * @private
28257 */\r
28258 bind: function() {\r
28259 var me = Ext.env.Ready,\r
28260 doc = document;\r
28261 if (!me.bound) {\r
28262 // Test scenario where load is dynamic AFTER window.load\r
28263 if (doc.readyState === 'complete') {\r
28264 // Firefox4+ got support for this state, others already do.\r
28265 me.onReadyEvent({\r
28266 type: doc.readyState || 'body'\r
28267 });\r
28268 } else {\r
28269 me.bound = 1;\r
28270 if (Ext.browser.is.PhoneGap && !Ext.os.is.Desktop) {\r
28271 me.bound = 2;\r
28272 doc.addEventListener('deviceready', me.onReadyEvent, false);\r
28273 }\r
28274 doc.addEventListener('DOMContentLoaded', me.onReadyEvent, false);\r
28275 window.addEventListener('load', me.onReadyEvent, false);\r
28276 }\r
28277 }\r
28278 },\r
28279 block: function() {\r
28280 ++this.blocks;\r
28281 Ext.isReady = false;\r
28282 },\r
28283 /**
28284 * This method starts the process of firing the ready event. This may be delayed based
28285 * on the `delay` property.
28286 * @private
28287 */\r
28288 fireReady: function() {\r
28289 var me = Ext.env.Ready;\r
28290 if (!me.state) {\r
28291 Ext._readyTime = Ext.ticks();\r
28292 Ext.isDomReady = true;\r
28293 me.state = 1;\r
28294 // As soon as we transition to domready, complete the feature detection:\r
28295 Ext.feature.detect(true);\r
28296 if (!me.delay) {\r
28297 me.handleReady();\r
28298 } else if (navigator.standalone) {\r
28299 // When running from Home Screen, the splash screen will not disappear\r
28300 // until all external resource requests finish.\r
28301 // The first timeout clears the splash screen\r
28302 // The second timeout allows inital HTML content to be displayed\r
28303 me.timer = Ext.defer(function() {\r
28304 me.timer = null;\r
28305 me.handleReadySoon();\r
28306 }, 1);\r
28307 } else {\r
28308 me.handleReadySoon();\r
28309 }\r
28310 }\r
28311 },\r
28312 /**
28313 * This method iterates over the `listeners` and invokes them. This advances the
28314 * `state` from 1 to 2 and ensure the proper subset of `listeners` are invoked.
28315 * @private
28316 */\r
28317 handleReady: function() {\r
28318 var me = this;\r
28319 if (me.state === 1) {\r
28320 me.state = 2;\r
28321 Ext._beforeReadyTime = Ext.ticks();\r
28322 me.invokeAll();\r
28323 Ext._afterReadyTime = Ext.ticks();\r
28324 }\r
28325 },\r
28326 /**
28327 * This method is called to schedule a call to `handleReady` using a `setTimeout`. It
28328 * ensures that only one timer is pending.
28329 * @param {Number} [delay] If passed, this overrides the `delay` property.
28330 * @private
28331 */\r
28332 handleReadySoon: function(delay) {\r
28333 var me = this;\r
28334 if (!me.timer) {\r
28335 me.timer = Ext.defer(function() {\r
28336 me.timer = null;\r
28337 me.handleReady();\r
28338 }, delay || me.delay);\r
28339 }\r
28340 },\r
28341 /**
28342 * This method invokes the given `listener` instance based on its options.
28343 * @param {Object} listener
28344 */\r
28345 invoke: function(listener) {\r
28346 var delay = listener.delay;\r
28347 if (delay) {\r
28348 Ext.defer(listener.fn, delay, listener.scope);\r
28349 } else {\r
28350 if (Ext.elevateFunction) {\r
28351 Ext.elevateFunction(listener.fn, listener.scope);\r
28352 } else {\r
28353 listener.fn.call(listener.scope);\r
28354 }\r
28355 }\r
28356 },\r
28357 /**
28358 * Invokes as many listeners as are appropriate given the current state. This should
28359 * only be called when DOM ready is achieved. The remaining business of `blocks` is
28360 * handled here.
28361 */\r
28362 invokeAll: function() {\r
28363 if (Ext.elevateFunction) {\r
28364 Ext.elevateFunction(this.doInvokeAll, this);\r
28365 } else {\r
28366 this.doInvokeAll();\r
28367 }\r
28368 },\r
28369 doInvokeAll: function() {\r
28370 var me = this,\r
28371 listeners = me.listeners,\r
28372 listener;\r
28373 if (!me.blocks) {\r
28374 // Since DOM is ready and we have no blocks, we mark the framework as ready.\r
28375 Ext.isReady = true;\r
28376 }\r
28377 me.firing = true;\r
28378 // NOTE: We cannot cache this length because each time through the loop a callback\r
28379 // may have added new callbacks.\r
28380 while (listeners.length) {\r
28381 if (me.sortGeneration !== me.generation) {\r
28382 me.sortGeneration = me.generation;\r
28383 // This will happen just once on the first pass... if nothing is being\r
28384 // added as we call the callbacks. This sorts the listeners such that the\r
28385 // highest priority listener is at the *end* of the array ... so we can\r
28386 // use pop (as opposed to shift) to extract it.\r
28387 listeners.sort(me.sortFn);\r
28388 }\r
28389 listener = listeners.pop();\r
28390 if (me.blocks && !listener.dom) {\r
28391 // If we are blocked (i.e., only DOM ready) and this listener is not a\r
28392 // DOM-ready listener we have reached the end of the line. The remaining\r
28393 // listeners are Framework ready listeners.\r
28394 listeners.push(listener);\r
28395 break;\r
28396 }\r
28397 me.invoke(listener);\r
28398 }\r
28399 me.firing = false;\r
28400 },\r
28401 /**
28402 * This method wraps the given listener pieces in a proper object for the `listeners`
28403 * array and `invoke` methods.
28404 * @param {Function} fn The method to call.
28405 * @param {Object} [scope] The scope (`this` reference) in which the `fn` executes.
28406 * Defaults to the browser window.
28407 * @param {Object} [options] An object with extra options.
28408 * @param {Number} [options.delay=0] A number of milliseconds to delay.
28409 * @param {Number} [options.priority=0] Relative priority of this callback. A larger
28410 * number will result in the callback being sorted before the others. Priorities
28411 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.
28412 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`
28413 * means full Framework and DOM readiness.
28414 * @return {Object} The listener instance.
28415 * @private
28416 */\r
28417 makeListener: function(fn, scope, options) {\r
28418 var ret = {\r
28419 fn: fn,\r
28420 id: ++this.nextId,\r
28421 // so sortFn can respect FIFO\r
28422 scope: scope,\r
28423 dom: false,\r
28424 priority: 0\r
28425 };\r
28426 if (options) {\r
28427 Ext.apply(ret, options);\r
28428 }\r
28429 ret.phase = ret.dom ? 0 : 1;\r
28430 // to simplify the sortFn\r
28431 return ret;\r
28432 },\r
28433 /**
28434 * Adds a listener to be notified when the document is ready (before onload and before
28435 * images are loaded).
28436 *
28437 * @param {Function} fn The method to call.
28438 * @param {Object} [scope] The scope (`this` reference) in which the `fn` executes.
28439 * Defaults to the browser window.
28440 * @param {Object} [options] An object with extra options.
28441 * @param {Number} [options.delay=0] A number of milliseconds to delay.
28442 * @param {Number} [options.priority=0] Relative priority of this callback. A larger
28443 * number will result in the callback being sorted before the others. Priorities
28444 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.
28445 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`
28446 * means full Framework and DOM readiness.
28447 * @private
28448 */\r
28449 on: function(fn, scope, options) {\r
28450 var me = Ext.env.Ready,\r
28451 listener = me.makeListener(fn, scope, options);\r
28452 if (me.state === 2 && !me.firing && (listener.dom || !me.blocks)) {\r
28453 // If we are DOM ready (state === 2) and not currently in invokeAll (!firing)\r
28454 // and this listener is ready to call (either a DOM ready listener or there\r
28455 // are no blocks), then we need to invoke the listener now.\r
28456 //\r
28457 // Otherwise we can fall to the else block and push the listener. The eventual\r
28458 // (or currently executing) call to handleReady or unblock will trigger its\r
28459 // delivery in proper priority order.\r
28460 me.invoke(listener);\r
28461 } else {\r
28462 me.listeners.push(listener);\r
28463 ++me.generation;\r
28464 if (!me.bound) {\r
28465 // If we have never bound then bind the ready event now. If we have unbound\r
28466 // the event then me.bound == -1 and we don't want to rebind it as the DOM\r
28467 // is ready.\r
28468 me.bind();\r
28469 }\r
28470 }\r
28471 },\r
28472 /**
28473 * This is a generic event handler method attached to all of the various events that
28474 * may indicate ready state. The first call to this method indicates ready state has
28475 * been achieved.
28476 * @param {Event} [ev] The event instance.
28477 * @private
28478 */\r
28479 onReadyEvent: function(ev) {\r
28480 var me = Ext.env.Ready;\r
28481 if (Ext.elevateFunction) {\r
28482 Ext.elevateFunction(me.doReadyEvent, me, arguments);\r
28483 } else {\r
28484 me.doReadyEvent(ev);\r
28485 }\r
28486 },\r
28487 doReadyEvent: function(ev) {\r
28488 var me = this;\r
28489 if (ev && ev.type) {\r
28490 me.events.push(ev);\r
28491 }\r
28492 if (me.bound > 0) {\r
28493 me.unbind();\r
28494 me.bound = -1;\r
28495 }\r
28496 // NOTE: *not* 0 or false - we never want to rebind!\r
28497 if (!me.state) {\r
28498 me.fireReady();\r
28499 }\r
28500 },\r
28501 /**
28502 * Sorts the `listeners` array by `phase` and `priority` such that the first listener
28503 * to fire can be determined using `pop` on the `listeners` array.
28504 * @private
28505 */\r
28506 sortFn: function(a, b) {\r
28507 return -((a.phase - b.phase) || (b.priority - a.priority) || (a.id - b.id));\r
28508 },\r
28509 unblock: function() {\r
28510 var me = this;\r
28511 if (me.blocks) {\r
28512 if (!--me.blocks) {\r
28513 if (me.state === 2 && !me.firing) {\r
28514 // We have already finished handleReady (the DOM ready handler) so\r
28515 // this trigger just needs to dispatch all the remaining listeners.\r
28516 me.invokeAll();\r
28517 }\r
28518 }\r
28519 }\r
28520 },\r
28521 // if we are currently firing then invokeAll will pick up the Framework\r
28522 // ready listeners automatically.\r
28523 //\r
28524 // If me.state < 2 then we are waiting for DOM ready so it will eventually\r
28525 // call handleReady and invokeAll when everything is ready.\r
28526 /**
28527 * This method is called to remove all event listeners that may have been set up to
28528 * detect ready state.
28529 * @private
28530 */\r
28531 unbind: function() {\r
28532 var me = this,\r
28533 doc = document;\r
28534 if (me.bound > 1) {\r
28535 doc.removeEventListener('deviceready', me.onReadyEvent, false);\r
28536 }\r
28537 doc.removeEventListener('DOMContentLoaded', me.onReadyEvent, false);\r
28538 window.removeEventListener('load', me.onReadyEvent, false);\r
28539 }\r
28540};\r
28541(function() {\r
28542 var Ready = Ext.env.Ready;\r
28543 /*
28544 * EXTJS-13522
28545 * Although IE 9 has the DOMContentLoaded event available, usage of that causes
28546 * timing issues when attempting to access document.namespaces (VmlCanvas.js).
28547 * Consequently, even in IE 9 we need to use the legacy bind override for ready
28548 * detection. This defers ready firing enough to allow access to the
28549 * document.namespaces property.
28550 *
28551 * NOTE: this issue is very timing sensitive, and typically only displays itself
28552 * when there is a large amount of latency between the browser and the server, and
28553 * when testing against a built page (ext-all.js) and not a dev mode page.
28554 */\r
28555 if (Ext.isIE9m) {\r
28556 /* Customized implementation for Legacy IE. The default implementation is
28557 * configured for use with all other 'standards compliant' agents.
28558 * References: http://javascript.nwbox.com/IEContentLoaded/
28559 * licensed courtesy of http://developer.yahoo.com/yui/license.html
28560 */\r
28561 Ext.apply(Ready, {\r
28562 /**
28563 * Timer for doScroll polling
28564 * @private
28565 */\r
28566 scrollTimer: null,\r
28567 /**
28568 * @private
28569 */\r
28570 readyStatesRe: /complete/i,\r
28571 /**
28572 * This strategy has minimal benefits for Sencha solutions that build
28573 * themselves (ie. minimal initial page markup). However, progressively-enhanced
28574 * pages (with image content and/or embedded frames) will benefit the most
28575 * from it. Browser timer resolution is too poor to ensure a doScroll check
28576 * more than once on a page loaded with minimal assets (the readystatechange
28577 * event 'complete' usually beats the doScroll timer on a 'lightly-loaded'
28578 * initial document).
28579 * @private
28580 */\r
28581 pollScroll: function() {\r
28582 var scrollable = true;\r
28583 try {\r
28584 document.documentElement.doScroll('left');\r
28585 } catch (e) {\r
28586 scrollable = false;\r
28587 }\r
28588 // on IE8, when running within an iFrame, document.body is not immediately\r
28589 // available\r
28590 if (scrollable && document.body) {\r
28591 Ready.onReadyEvent({\r
28592 type: 'doScroll'\r
28593 });\r
28594 } else {\r
28595 // Minimize thrashing --\r
28596 // adjusted for setTimeout's close-to-minimums (not too low),\r
28597 // as this method SHOULD always be called once initially\r
28598 Ready.scrollTimer = Ext.defer(Ready.pollScroll, 20);\r
28599 }\r
28600 return scrollable;\r
28601 },\r
28602 bind: function() {\r
28603 if (Ready.bound) {\r
28604 return;\r
28605 }\r
28606 var doc = document,\r
28607 topContext;\r
28608 // See if we are in an IFRAME? (doScroll ineffective here)\r
28609 try {\r
28610 topContext = window.frameElement === undefined;\r
28611 } catch (e) {}\r
28612 // If we throw an exception, it means we're probably getting access\r
28613 // denied, which means we're in an iframe cross domain.\r
28614 if (!topContext || !doc.documentElement.doScroll) {\r
28615 Ready.pollScroll = Ext.emptyFn;\r
28616 }\r
28617 //then noop this test altogether\r
28618 else if (Ready.pollScroll()) {\r
28619 // starts scroll polling if necessary\r
28620 return;\r
28621 }\r
28622 if (doc.readyState === 'complete') {\r
28623 // Loaded AFTER initial document write/load...\r
28624 Ready.onReadyEvent({\r
28625 type: 'already ' + (doc.readyState || 'body')\r
28626 });\r
28627 } else {\r
28628 doc.attachEvent('onreadystatechange', Ready.onReadyStateChange);\r
28629 window.attachEvent('onload', Ready.onReadyEvent);\r
28630 Ready.bound = 1;\r
28631 }\r
28632 },\r
28633 unbind: function() {\r
28634 document.detachEvent('onreadystatechange', Ready.onReadyStateChange);\r
28635 window.detachEvent('onload', Ready.onReadyEvent);\r
28636 if (Ext.isNumber(Ready.scrollTimer)) {\r
28637 clearTimeout(Ready.scrollTimer);\r
28638 Ready.scrollTimer = null;\r
28639 }\r
28640 },\r
28641 /**
28642 * This event handler is called when the readyState changes.
28643 * @private
28644 */\r
28645 onReadyStateChange: function() {\r
28646 var state = document.readyState;\r
28647 if (Ready.readyStatesRe.test(state)) {\r
28648 Ready.onReadyEvent({\r
28649 type: state\r
28650 });\r
28651 }\r
28652 }\r
28653 });\r
28654 }\r
28655 /**
28656 * @property {Boolean} isDomReady
28657 * `true` when the document body is ready for use.
28658 * @member Ext
28659 * @readonly
28660 */\r
28661 /**
28662 * @property {Boolean} isReady
28663 * `true` when `isDomReady` is true and the Framework is ready for use.
28664 * @member Ext
28665 * @readonly
28666 */\r
28667 /**
28668 * @method onDocumentReady
28669 * @member Ext
28670 * Adds a listener to be notified when the document is ready (before onload and before
28671 * images are loaded).
28672 *
28673 * @param {Function} fn The method to call.
28674 * @param {Object} [scope] The scope (`this` reference) in which the handler function
28675 * executes. Defaults to the browser window.
28676 * @param {Object} [options] An object with extra options.
28677 * @param {Number} [options.delay=0] A number of milliseconds to delay.
28678 * @param {Number} [options.priority=0] Relative priority of this callback. A larger
28679 * number will result in the callback being sorted before the others. Priorities
28680 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.
28681 * @private
28682 */\r
28683 Ext.onDocumentReady = function(fn, scope, options) {\r
28684 var opt = {\r
28685 dom: true\r
28686 };\r
28687 if (options) {\r
28688 Ext.apply(opt, options);\r
28689 }\r
28690 Ready.on(fn, scope, opt);\r
28691 };\r
28692 /**
28693 * @method onReady
28694 * @member Ext
28695 * Adds a listener to be notified when the document is ready (before onload and before
28696 * images are loaded).
28697 *
28698 * @param {Function} fn The method to call.
28699 * @param {Object} [scope] The scope (`this` reference) in which the handler function
28700 * executes. Defaults to the browser window.
28701 * @param {Object} [options] An object with extra options.
28702 * @param {Number} [options.delay=0] A number of milliseconds to delay.
28703 * @param {Number} [options.priority=0] Relative priority of this callback. A larger
28704 * number will result in the callback being sorted before the others. Priorities
28705 * 1000 or greater and -1000 or lesser are reserved for internal framework use only.
28706 * @param {Boolean} [options.dom=false] Pass `true` to only wait for DOM ready, `false`
28707 * means full Framework and DOM readiness.
28708 * numbers are reserved.
28709 */\r
28710 Ext.onReady = function(fn, scope, options) {\r
28711 Ready.on(fn, scope, options);\r
28712 };\r
28713 // A shortcut method for onReady with a high priority\r
28714 Ext.onInternalReady = function(fn, scope, options) {\r
28715 Ready.on(fn, scope, Ext.apply({\r
28716 priority: 1000\r
28717 }, options));\r
28718 };\r
28719 Ready.bind();\r
28720}());\r
28721\r
28722// @tag class\r
28723/**
28724 * This class provides dynamic loading support for JavaScript classes. Application code
28725 * does not typically need to call `Ext.Loader` except perhaps to configure path mappings
28726 * when not using [Sencha Cmd](http://www.sencha.com/products/sencha-cmd/).
28727 *
28728 * Ext.Loader.setPath('MyApp', 'app');
28729 *
28730 * When using Sencha Cmd, this is handled by the "bootstrap" provided by the application
28731 * build script and such configuration is not necessary.
28732 *
28733 * # Typical Usage
28734 *
28735 * The `Ext.Loader` is most often used behind the scenes to satisfy class references in
28736 * class declarations. Like so:
28737 *
28738 * Ext.define('MyApp.view.Main', {
28739 * extend: 'Ext.panel.Panel',
28740 *
28741 * mixins: [
28742 * 'MyApp.util.Mixin'
28743 * ],
28744 *
28745 * requires: [
28746 * 'Ext.grid.Panel'
28747 * ],
28748 *
28749 * uses: [
28750 * 'MyApp.util.Stuff'
28751 * ]
28752 * });
28753 *
28754 * In all of these cases, `Ext.Loader` is used internally to resolve these class names
28755 * and ensure that the necessary class files are loaded.
28756 *
28757 * During development, these files are loaded individually for optimal debugging. For a
28758 * production use, [Sencha Cmd](http://www.sencha.com/products/sencha-cmd/) will replace
28759 * all of these strings with the actual resolved class references because it ensures that
28760 * the classes are all contained in the build in the correct order. In development, these
28761 * files will not be loaded until the `MyApp.view.Main` class indicates they are needed
28762 * as shown above.
28763 *
28764 * # Loading Classes
28765 *
28766 * You can also use `Ext.Loader` directly to load classes or files. The simplest form of
28767 * use is `{@link Ext#require}`.
28768 *
28769 * For example:
28770 *
28771 * Ext.require('MyApp.view.Main', function () {
28772 * // On callback, the MyApp.view.Main class is now loaded
28773 *
28774 * var view = new MyApp.view.Main();
28775 * });
28776 *
28777 * You can alternatively require classes by alias or wildcard.
28778 *
28779 * Ext.require('widget.window');
28780 *
28781 * Ext.require(['widget.window', 'layout.border', 'Ext.data.Connection']);
28782 *
28783 * Ext.require(['widget.*', 'layout.*', 'Ext.data.*']);
28784 *
28785 * The callback function is optional.
28786 *
28787 * **Note** Using `Ext.require` at global scope will cause `{@link Ext#onReady}` and
28788 * `{@link Ext.app.Application#launch}` methods to be deferred until the required classes
28789 * are loaded. It is these cases where the callback function is most often unnecessary.
28790 *
28791 * ## Using Excludes
28792 *
28793 * Alternatively, you can exclude what you don't need:
28794 *
28795 * // Include everything except Ext.tree.*
28796 * Ext.exclude('Ext.tree.*').require('*');
28797 *
28798 * // Include all widgets except widget.checkbox* (this will exclude
28799 * // widget.checkbox, widget.checkboxfield, widget.checkboxgroup, etc.)
28800 * Ext.exclude('widget.checkbox*').require('widget.*');
28801 *
28802 * # Dynamic Instantiation
28803 *
28804 * Another feature enabled by `Ext.Loader` is instantiation using class names or aliases.
28805 *
28806 * For example:
28807 *
28808 * var win = Ext.create({
28809 * xtype: 'window',
28810 *
28811 * // or
28812 * // xclass: 'Ext.window.Window'
28813 *
28814 * title: 'Hello'
28815 * });
28816 *
28817 * This form of creation can be useful if the type to create (`window` in the above) is
28818 * not known statically. Internally, `{@link Ext#create}` may need to *synchronously*
28819 * load the desired class and its requirements. Doing this will generate a warning in
28820 * the console:
28821 *
28822 * [Ext.Loader] Synchronously loading 'Ext.window.Window'...
28823 *
28824 * If you see these in your debug console, you should add the indicated class(es) to the
28825 * appropriate `requires` array (as above) or make an `{@link Ext#require}` call.
28826 *
28827 *
28828 * **Note** Using `{@link Ext#create}` has some performance overhead and is best reserved
28829 * for cases where the target class is not known until run-time.
28830 *
28831 * @class Ext.Loader
28832 * @singleton
28833 */\r
28834Ext.Loader = (new function() {\r
28835 // jshint ignore:line\r
28836 // @define Ext.Loader\r
28837 // @require Ext.Base\r
28838 // @require Ext.Class\r
28839 // @require Ext.ClassManager\r
28840 // @require Ext.Function\r
28841 // @require Ext.Array\r
28842 // @require Ext.env.Ready\r
28843 var Loader = this,\r
28844 Manager = Ext.ClassManager,\r
28845 // this is an instance of Ext.Inventory\r
28846 Boot = Ext.Boot,\r
28847 Class = Ext.Class,\r
28848 Ready = Ext.env.Ready,\r
28849 alias = Ext.Function.alias,\r
28850 dependencyProperties = [\r
28851 'extend',\r
28852 'mixins',\r
28853 'requires'\r
28854 ],\r
28855 isInHistory = {},\r
28856 history = [],\r
28857 readyListeners = [],\r
28858 usedClasses = [],\r
28859 _requiresMap = {},\r
28860 _missingQueue = {},\r
28861 _config = {\r
28862 /**
28863 * @cfg {Boolean} [enabled=true]
28864 * Whether or not to enable the dynamic dependency loading feature.
28865 */\r
28866 enabled: true,\r
28867 /**
28868 * @cfg {Boolean} [scriptChainDelay=false]
28869 * millisecond delay between asynchronous script injection (prevents stack
28870 * overflow on some user agents) 'false' disables delay but potentially
28871 * increases stack load.
28872 */\r
28873 scriptChainDelay: false,\r
28874 /**
28875 * @cfg {Boolean} [disableCaching=true]
28876 * Appends current timestamp to script files to prevent caching.
28877 */\r
28878 disableCaching: true,\r
28879 /**
28880 * @cfg {String} [disableCachingParam="_dc"]
28881 * The get parameter name for the cache buster's timestamp.
28882 */\r
28883 disableCachingParam: '_dc',\r
28884 /**
28885 * @cfg {Object} paths
28886 * The mapping from namespaces to file paths
28887 *
28888 * {
28889 * 'Ext': '.', // This is set by default, Ext.layout.container.Container will be
28890 * // loaded from ./layout/Container.js
28891 *
28892 * 'My': './src/my_own_folder' // My.layout.Container will be loaded from
28893 * // ./src/my_own_folder/layout/Container.js
28894 * }
28895 *
28896 * Note that all relative paths are relative to the current HTML document.
28897 * If not being specified, for example, `Other.awesome.Class` will simply be
28898 * loaded from `"./Other/awesome/Class.js"`.
28899 */\r
28900 paths: Manager.paths,\r
28901 /**
28902 * @cfg {Boolean} preserveScripts
28903 * `false` to remove asynchronously loaded scripts, `true` to retain script
28904 * element for browser debugger compatibility and improved load performance.
28905 */\r
28906 preserveScripts: true,\r
28907 /**
28908 * @cfg {String} scriptCharset
28909 * Optional charset to specify encoding of dynamic script content.
28910 */\r
28911 scriptCharset: undefined\r
28912 },\r
28913 // These configs are delegated to Ext.Script and may need different names:\r
28914 delegatedConfigs = {\r
28915 disableCaching: true,\r
28916 disableCachingParam: true,\r
28917 preserveScripts: true,\r
28918 scriptChainDelay: 'loadDelay'\r
28919 };\r
28920 Ext.apply(Loader, {\r
28921 /**
28922 * @private
28923 */\r
28924 isInHistory: isInHistory,\r
28925 /**
28926 * Flag indicating whether there are still files being loaded
28927 * @private
28928 */\r
28929 isLoading: false,\r
28930 /**
28931 * An array of class names to keep track of the dependency loading order.
28932 * This is not guaranteed to be the same everytime due to the asynchronous
28933 * nature of the Loader.
28934 *
28935 * @property {Array} history
28936 */\r
28937 history: history,\r
28938 /**
28939 * Configuration
28940 * @private
28941 */\r
28942 config: _config,\r
28943 /**
28944 * Maintain the list of listeners to execute when all required scripts are fully loaded
28945 * @private
28946 */\r
28947 readyListeners: readyListeners,\r
28948 /**
28949 * Contains classes referenced in `uses` properties.
28950 * @private
28951 */\r
28952 optionalRequires: usedClasses,\r
28953 /**
28954 * Map of fully qualified class names to an array of dependent classes.
28955 * @private
28956 */\r
28957 requiresMap: _requiresMap,\r
28958 /** @private */\r
28959 hasFileLoadError: false,\r
28960 /**
28961 * The number of scripts loading via loadScript.
28962 * @private
28963 */\r
28964 scriptsLoading: 0,\r
28965 /**
28966 * @private
28967 */\r
28968 classesLoading: [],\r
28969 /**
28970 * @private
28971 */\r
28972 syncModeEnabled: false,\r
28973 /**
28974 * @private
28975 */\r
28976 missingQueue: _missingQueue,\r
28977 init: function() {\r
28978 // initalize the default path of the framework\r
28979 var scripts = document.getElementsByTagName('script'),\r
28980 src = scripts[scripts.length - 1].src,\r
28981 path = src.substring(0, src.lastIndexOf('/') + 1),\r
28982 meta = Ext._classPathMetadata,\r
28983 microloader = Ext.Microloader,\r
28984 manifest = Ext.manifest,\r
28985 loadOrder, baseUrl, loadlen, l, loadItem;\r
28986 if (src.indexOf("packages/core/src/") !== -1) {\r
28987 path = path + "../../";\r
28988 } else if (src.indexOf("/core/src/class/") !== -1) {\r
28989 path = path + "../../../";\r
28990 }\r
28991 if (!Manager.getPath("Ext")) {\r
28992 Manager.setPath('Ext', path + 'src');\r
28993 }\r
28994 // Pull in Cmd generated metadata if available.\r
28995 if (meta) {\r
28996 Ext._classPathMetadata = null;\r
28997 Loader.addClassPathMappings(meta);\r
28998 }\r
28999 if (manifest) {\r
29000 loadOrder = manifest.loadOrder;\r
29001 // if the manifest paths were calculated as relative to the \r
29002 // bootstrap file, then we need to prepend Boot.baseUrl to the\r
29003 // paths before processing\r
29004 baseUrl = Ext.Boot.baseUrl;\r
29005 if (loadOrder && manifest.bootRelative) {\r
29006 for (loadlen = loadOrder.length , l = 0; l < loadlen; l++) {\r
29007 loadItem = loadOrder[l];\r
29008 loadItem.path = baseUrl + loadItem.path;\r
29009 }\r
29010 }\r
29011 }\r
29012 if (microloader) {\r
29013 Ready.block();\r
29014 microloader.onMicroloaderReady(function() {\r
29015 Ready.unblock();\r
29016 });\r
29017 }\r
29018 },\r
29019 /**
29020 * Set the configuration for the loader. This should be called right after ext-(debug).js
29021 * is included in the page, and before Ext.onReady. i.e:
29022 *
29023 * <script type="text/javascript" src="ext-core-debug.js"></script>
29024 * <script type="text/javascript">
29025 * Ext.Loader.setConfig({
29026 * enabled: true,
29027 * paths: {
29028 * 'My': 'my_own_path'
29029 * }
29030 * });
29031 * </script>
29032 * <script type="text/javascript">
29033 * Ext.require(...);
29034 *
29035 * Ext.onReady(function() {
29036 * // application code here
29037 * });
29038 * </script>
29039 *
29040 * Refer to config options of {@link Ext.Loader} for the list of possible properties
29041 *
29042 * @param {Object} config The config object to override the default values
29043 * @return {Ext.Loader} this
29044 */\r
29045 setConfig: Ext.Function.flexSetter(function(name, value) {\r
29046 if (name === 'paths') {\r
29047 Loader.setPath(value);\r
29048 } else {\r
29049 _config[name] = value;\r
29050 var delegated = delegatedConfigs[name];\r
29051 if (delegated) {\r
29052 Boot.setConfig((delegated === true) ? name : delegated, value);\r
29053 }\r
29054 }\r
29055 return Loader;\r
29056 }),\r
29057 /**
29058 * Get the config value corresponding to the specified name. If no name is given, will return the config object
29059 * @param {String} name The config property name
29060 * @return {Object}
29061 */\r
29062 getConfig: function(name) {\r
29063 return name ? _config[name] : _config;\r
29064 },\r
29065 /**
29066 * Sets the path of a namespace.
29067 * For Example:
29068 *
29069 * Ext.Loader.setPath('Ext', '.');
29070 *
29071 * @param {String/Object} name See {@link Ext.Function#flexSetter flexSetter}
29072 * @param {String} [path] See {@link Ext.Function#flexSetter flexSetter}
29073 * @return {Ext.Loader} this
29074 * @method
29075 */\r
29076 setPath: function() {\r
29077 // Paths are an Ext.Inventory thing and ClassManager is an instance of that:\r
29078 Manager.setPath.apply(Manager, arguments);\r
29079 return Loader;\r
29080 },\r
29081 /**
29082 * Sets a batch of path entries
29083 *
29084 * @param {Object } paths a set of className: path mappings
29085 * @return {Ext.Loader} this
29086 */\r
29087 addClassPathMappings: function(paths) {\r
29088 // Paths are an Ext.Inventory thing and ClassManager is an instance of that:\r
29089 Manager.setPath(paths);\r
29090 return Loader;\r
29091 },\r
29092 /**
29093 * fixes up loader path configs by prepending Ext.Boot#baseUrl to the beginning
29094 * of the path, then delegates to Ext.Loader#addClassPathMappings
29095 * @param pathConfig
29096 */\r
29097 addBaseUrlClassPathMappings: function(pathConfig) {\r
29098 for (var name in pathConfig) {\r
29099 pathConfig[name] = Boot.baseUrl + pathConfig[name];\r
29100 }\r
29101 Ext.Loader.addClassPathMappings(pathConfig);\r
29102 },\r
29103 /**
29104 * Translates a className to a file path by adding the
29105 * the proper prefix and converting the .'s to /'s. For example:
29106 *
29107 * Ext.Loader.setPath('My', '/path/to/My');
29108 *
29109 * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/path/to/My/awesome/Class.js'
29110 *
29111 * Note that the deeper namespace levels, if explicitly set, are always resolved first. For example:
29112 *
29113 * Ext.Loader.setPath({
29114 * 'My': '/path/to/lib',
29115 * 'My.awesome': '/other/path/for/awesome/stuff',
29116 * 'My.awesome.more': '/more/awesome/path'
29117 * });
29118 *
29119 * alert(Ext.Loader.getPath('My.awesome.Class')); // alerts '/other/path/for/awesome/stuff/Class.js'
29120 *
29121 * alert(Ext.Loader.getPath('My.awesome.more.Class')); // alerts '/more/awesome/path/Class.js'
29122 *
29123 * alert(Ext.Loader.getPath('My.cool.Class')); // alerts '/path/to/lib/cool/Class.js'
29124 *
29125 * alert(Ext.Loader.getPath('Unknown.strange.Stuff')); // alerts 'Unknown/strange/Stuff.js'
29126 *
29127 * @param {String} className
29128 * @return {String} path
29129 */\r
29130 getPath: function(className) {\r
29131 // Paths are an Ext.Inventory thing and ClassManager is an instance of that:\r
29132 return Manager.getPath(className);\r
29133 },\r
29134 require: function(expressions, fn, scope, excludes) {\r
29135 if (excludes) {\r
29136 return Loader.exclude(excludes).require(expressions, fn, scope);\r
29137 }\r
29138 var classNames = Manager.getNamesByExpression(expressions);\r
29139 return Loader.load(classNames, fn, scope);\r
29140 },\r
29141 syncRequire: function() {\r
29142 var wasEnabled = Loader.syncModeEnabled;\r
29143 Loader.syncModeEnabled = true;\r
29144 var ret = Loader.require.apply(Loader, arguments);\r
29145 Loader.syncModeEnabled = wasEnabled;\r
29146 return ret;\r
29147 },\r
29148 exclude: function(excludes) {\r
29149 var selector = Manager.select({\r
29150 require: function(classNames, fn, scope) {\r
29151 return Loader.load(classNames, fn, scope);\r
29152 },\r
29153 syncRequire: function(classNames, fn, scope) {\r
29154 var wasEnabled = Loader.syncModeEnabled;\r
29155 Loader.syncModeEnabled = true;\r
29156 var ret = Loader.load(classNames, fn, scope);\r
29157 Loader.syncModeEnabled = wasEnabled;\r
29158 return ret;\r
29159 }\r
29160 });\r
29161 selector.exclude(excludes);\r
29162 return selector;\r
29163 },\r
29164 load: function(classNames, callback, scope) {\r
29165 if (callback) {\r
29166 if (callback.length) {\r
29167 // If callback expects arguments, shim it with a function that will map\r
29168 // the requires class(es) from the names we are given.\r
29169 callback = Loader.makeLoadCallback(classNames, callback);\r
29170 }\r
29171 callback = callback.bind(scope || Ext.global);\r
29172 }\r
29173 var missingClassNames = [],\r
29174 numClasses = classNames.length,\r
29175 className, i, numMissing,\r
29176 urls = [],\r
29177 state = Manager.classState;\r
29178 for (i = 0; i < numClasses; ++i) {\r
29179 className = Manager.resolveName(classNames[i]);\r
29180 if (!Manager.isCreated(className)) {\r
29181 missingClassNames.push(className);\r
29182 _missingQueue[className] = Loader.getPath(className);\r
29183 if (!state[className]) {\r
29184 urls.push(_missingQueue[className]);\r
29185 }\r
29186 }\r
29187 }\r
29188 // If the dynamic dependency feature is not being used, throw an error\r
29189 // if the dependencies are not defined\r
29190 numMissing = missingClassNames.length;\r
29191 if (numMissing) {\r
29192 Loader.missingCount += numMissing;\r
29193 Ext.Array.push(Loader.classesLoading, missingClassNames);\r
29194 Manager.onCreated(function() {\r
29195 Ext.Array.remove(Loader.classesLoading, missingClassNames);\r
29196 Ext.each(missingClassNames, function(name) {\r
29197 Ext.Array.remove(Loader.classesLoading, name);\r
29198 });\r
29199 if (callback) {\r
29200 Ext.callback(callback, scope, arguments);\r
29201 }\r
29202 Loader.checkReady();\r
29203 }, Loader, missingClassNames);\r
29204 if (!_config.enabled) {\r
29205 Ext.raise("Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " + "Missing required class" + ((missingClassNames.length > 1) ? "es" : "") + ": " + missingClassNames.join(', '));\r
29206 }\r
29207 if (urls.length) {\r
29208 Loader.loadScripts({\r
29209 url: urls,\r
29210 // scope: this options object so we can pass these along:\r
29211 _classNames: missingClassNames\r
29212 });\r
29213 } else {\r
29214 // need to call checkReady here, as the _missingCoun\r
29215 // may have transitioned from 0 to > 0, meaning we\r
29216 // need to block ready\r
29217 Loader.checkReady();\r
29218 }\r
29219 } else {\r
29220 if (callback) {\r
29221 callback.call(scope);\r
29222 }\r
29223 // need to call checkReady here, as the _missingCoun\r
29224 // may have transitioned from 0 to > 0, meaning we\r
29225 // need to block ready\r
29226 Loader.checkReady();\r
29227 }\r
29228 if (Loader.syncModeEnabled) {\r
29229 // Class may have been just loaded or was already loaded\r
29230 if (numClasses === 1) {\r
29231 return Manager.get(classNames[0]);\r
29232 }\r
29233 }\r
29234 return Loader;\r
29235 },\r
29236 makeLoadCallback: function(classNames, callback) {\r
29237 return function() {\r
29238 var classes = [],\r
29239 i = classNames.length;\r
29240 while (i-- > 0) {\r
29241 classes[i] = Manager.get(classNames[i]);\r
29242 }\r
29243 return callback.apply(this, classes);\r
29244 };\r
29245 },\r
29246 onLoadFailure: function() {\r
29247 var options = this,\r
29248 onError = options.onError;\r
29249 Loader.hasFileLoadError = true;\r
29250 --Loader.scriptsLoading;\r
29251 if (onError) {\r
29252 //TODO: need an adapter to convert to v4 onError signatures\r
29253 onError.call(options.userScope, options);\r
29254 } else {\r
29255 Ext.log.error("[Ext.Loader] Some requested files failed to load.");\r
29256 }\r
29257 Loader.checkReady();\r
29258 },\r
29259 onLoadSuccess: function() {\r
29260 var options = this,\r
29261 onLoad = options.onLoad;\r
29262 --Loader.scriptsLoading;\r
29263 if (onLoad) {\r
29264 //TODO: need an adapter to convert to v4 onLoad signatures\r
29265 onLoad.call(options.userScope, options);\r
29266 }\r
29267 // onLoad can cause more loads to start, so it must run first\r
29268 Loader.checkReady();\r
29269 },\r
29270 // TODO: this timing of this needs to be deferred until all classes have had a chance to be created\r
29271 reportMissingClasses: function() {\r
29272 if (!Loader.syncModeEnabled && !Loader.scriptsLoading && Loader.isLoading && !Loader.hasFileLoadError) {\r
29273 var missingClasses = [],\r
29274 missingPaths = [];\r
29275 for (var missingClassName in _missingQueue) {\r
29276 missingClasses.push(missingClassName);\r
29277 missingPaths.push(_missingQueue[missingClassName]);\r
29278 }\r
29279 if (missingClasses.length) {\r
29280 throw new Error("The following classes are not declared even if their files have been " + "loaded: '" + missingClasses.join("', '") + "'. Please check the source code of their " + "corresponding files for possible typos: '" + missingPaths.join("', '"));\r
29281 }\r
29282 }\r
29283 },\r
29284 /**
29285 * Add a new listener to be executed when all required scripts are fully loaded
29286 *
29287 * @param {Function} fn The function callback to be executed
29288 * @param {Object} scope The execution scope (`this`) of the callback function.
29289 * @param {Boolean} [withDomReady=true] Pass `false` to not also wait for document
29290 * dom ready.
29291 * @param {Object} [options] Additional callback options.
29292 * @param {Number} [options.delay=0] A number of milliseconds to delay.
29293 * @param {Number} [options.priority=0] Relative priority of this callback. Negative
29294 * numbers are reserved.
29295 */\r
29296 onReady: function(fn, scope, withDomReady, options) {\r
29297 if (withDomReady) {\r
29298 Ready.on(fn, scope, options);\r
29299 } else {\r
29300 var listener = Ready.makeListener(fn, scope, options);\r
29301 if (Loader.isLoading) {\r
29302 readyListeners.push(listener);\r
29303 } else {\r
29304 Ready.invoke(listener);\r
29305 }\r
29306 }\r
29307 },\r
29308 /**
29309 * @private
29310 * Ensure that any classes referenced in the `uses` property are loaded.
29311 */\r
29312 addUsedClasses: function(classes) {\r
29313 var cls, i, ln;\r
29314 if (classes) {\r
29315 classes = (typeof classes === 'string') ? [\r
29316 classes\r
29317 ] : classes;\r
29318 for (i = 0 , ln = classes.length; i < ln; i++) {\r
29319 cls = classes[i];\r
29320 if (typeof cls === 'string' && !Ext.Array.contains(usedClasses, cls)) {\r
29321 usedClasses.push(cls);\r
29322 }\r
29323 }\r
29324 }\r
29325 return Loader;\r
29326 },\r
29327 /**
29328 * @private
29329 */\r
29330 triggerReady: function() {\r
29331 var listener,\r
29332 refClasses = usedClasses;\r
29333 if (Loader.isLoading && refClasses.length) {\r
29334 // Empty the array to eliminate potential recursive loop issue\r
29335 usedClasses = [];\r
29336 // this may immediately call us back if all 'uses' classes\r
29337 // have been loaded\r
29338 Loader.require(refClasses);\r
29339 } else {\r
29340 // Must clear this before calling callbacks. This will cause any new loads\r
29341 // to call Ready.block() again. See below for more on this.\r
29342 Loader.isLoading = false;\r
29343 // These listeners are just those attached directly to Loader to wait for\r
29344 // class loading only.\r
29345 readyListeners.sort(Ready.sortFn);\r
29346 // this method can be called with Loader.isLoading either true or false\r
29347 // (can be called with false when all 'uses' classes are already loaded)\r
29348 // this may bypass the above if condition\r
29349 while (readyListeners.length && !Loader.isLoading) {\r
29350 // we may re-enter triggerReady so we cannot necessarily iterate the\r
29351 // readyListeners array\r
29352 listener = readyListeners.pop();\r
29353 Ready.invoke(listener);\r
29354 }\r
29355 // If the DOM is also ready, this will fire the normal onReady listeners.\r
29356 // An astute observer would note that we may now be back to isLoading and\r
29357 // so ask "Why you call unblock?". The reason is that we must match the\r
29358 // calls to block and since we transitioned from isLoading to !isLoading\r
29359 // here we must call unblock. If we have transitioned back to isLoading in\r
29360 // the above loop it will have called block again so the counter will be\r
29361 // increased and this call will not reduce the block count to 0. This is\r
29362 // done by loadScripts.\r
29363 Ready.unblock();\r
29364 }\r
29365 },\r
29366 /**
29367 * @private
29368 * @param {String} className
29369 */\r
29370 historyPush: function(className) {\r
29371 if (className && !isInHistory[className] && !Manager.overrideMap[className]) {\r
29372 isInHistory[className] = true;\r
29373 history.push(className);\r
29374 }\r
29375 return Loader;\r
29376 },\r
29377 /**
29378 * This is an internal method that delegate content loading to the
29379 * bootstrap layer.
29380 * @private
29381 * @param params
29382 */\r
29383 loadScripts: function(params) {\r
29384 var manifest = Ext.manifest,\r
29385 loadOrder = manifest && manifest.loadOrder,\r
29386 loadOrderMap = manifest && manifest.loadOrderMap,\r
29387 options;\r
29388 ++Loader.scriptsLoading;\r
29389 // if the load order map hasn't been created, create it now \r
29390 // and cache on the manifest\r
29391 if (loadOrder && !loadOrderMap) {\r
29392 manifest.loadOrderMap = loadOrderMap = Boot.createLoadOrderMap(loadOrder);\r
29393 }\r
29394 // verify the loading state, as this may have transitioned us from\r
29395 // not loading to loading\r
29396 Loader.checkReady();\r
29397 options = Ext.apply({\r
29398 loadOrder: loadOrder,\r
29399 loadOrderMap: loadOrderMap,\r
29400 charset: _config.scriptCharset,\r
29401 success: Loader.onLoadSuccess,\r
29402 failure: Loader.onLoadFailure,\r
29403 sync: Loader.syncModeEnabled,\r
29404 _classNames: []\r
29405 }, params);\r
29406 options.userScope = options.scope;\r
29407 options.scope = options;\r
29408 Boot.load(options);\r
29409 },\r
29410 /**
29411 * This method is provide for use by the bootstrap layer.
29412 * @private
29413 * @param {String[]} urls
29414 */\r
29415 loadScriptsSync: function(urls) {\r
29416 var syncwas = Loader.syncModeEnabled;\r
29417 Loader.syncModeEnabled = true;\r
29418 Loader.loadScripts({\r
29419 url: urls\r
29420 });\r
29421 Loader.syncModeEnabled = syncwas;\r
29422 },\r
29423 /**
29424 * This method is provide for use by the bootstrap layer.
29425 * @private
29426 * @param {String[]} urls
29427 */\r
29428 loadScriptsSyncBasePrefix: function(urls) {\r
29429 var syncwas = Loader.syncModeEnabled;\r
29430 Loader.syncModeEnabled = true;\r
29431 Loader.loadScripts({\r
29432 url: urls,\r
29433 prependBaseUrl: true\r
29434 });\r
29435 Loader.syncModeEnabled = syncwas;\r
29436 },\r
29437 /**
29438 * Loads the specified script URL and calls the supplied callbacks. If this method
29439 * is called before {@link Ext#isReady}, the script's load will delay the transition
29440 * to ready. This can be used to load arbitrary scripts that may contain further
29441 * {@link Ext#require Ext.require} calls.
29442 *
29443 * @param {Object/String/String[]} options The options object or simply the URL(s) to load.
29444 * @param {String} options.url The URL from which to load the script.
29445 * @param {Function} [options.onLoad] The callback to call on successful load.
29446 * @param {Function} [options.onError] The callback to call on failure to load.
29447 * @param {Object} [options.scope] The scope (`this`) for the supplied callbacks.
29448 */\r
29449 loadScript: function(options) {\r
29450 var isString = typeof options === 'string',\r
29451 isArray = options instanceof Array,\r
29452 isObject = !isArray && !isString,\r
29453 url = isObject ? options.url : options,\r
29454 onError = isObject && options.onError,\r
29455 onLoad = isObject && options.onLoad,\r
29456 scope = isObject && options.scope,\r
29457 request = {\r
29458 url: url,\r
29459 scope: scope,\r
29460 onLoad: onLoad,\r
29461 onError: onError,\r
29462 _classNames: []\r
29463 };\r
29464 Loader.loadScripts(request);\r
29465 },\r
29466 /**
29467 * @private
29468 */\r
29469 flushMissingQueue: function() {\r
29470 var name, val,\r
29471 missingwas = 0,\r
29472 missing = 0;\r
29473 for (name in _missingQueue) {\r
29474 missingwas++;\r
29475 val = _missingQueue[name];\r
29476 if (Manager.isCreated(name)) {\r
29477 delete _missingQueue[name];\r
29478 } else if (Manager.existCache[name] === 2) {\r
29479 delete _missingQueue[name];\r
29480 } else {\r
29481 ++missing;\r
29482 }\r
29483 }\r
29484 this.missingCount = missing;\r
29485 },\r
29486 /**
29487 * @private
29488 */\r
29489 checkReady: function() {\r
29490 var wasLoading = Loader.isLoading,\r
29491 isLoading;\r
29492 Loader.flushMissingQueue();\r
29493 isLoading = Loader.missingCount + Loader.scriptsLoading;\r
29494 if (isLoading && !wasLoading) {\r
29495 Ready.block();\r
29496 Loader.isLoading = !!isLoading;\r
29497 } else if (!isLoading && wasLoading) {\r
29498 Loader.triggerReady();\r
29499 }\r
29500 if (!Loader.scriptsLoading && Loader.missingCount) {\r
29501 // Things look bad, but since load requests may come later, defer this\r
29502 // for a bit then check if things are still stuck.\r
29503 Ext.defer(function() {\r
29504 if (!Loader.scriptsLoading && Loader.missingCount) {\r
29505 Ext.log.error('[Loader] The following classes failed to load:');\r
29506 for (var name in Loader.missingQueue) {\r
29507 Ext.log.error('[Loader] ' + name + ' from ' + Loader.missingQueue[name]);\r
29508 }\r
29509 }\r
29510 }, 1000);\r
29511 }\r
29512 }\r
29513 });\r
29514 /**
29515 * Loads all classes by the given names and all their direct dependencies; optionally
29516 * executes the given callback function when finishes, within the optional scope.
29517 *
29518 * @param {String/String[]} expressions The class, classes or wildcards to load.
29519 * @param {Function} [fn] The callback function.
29520 * @param {Object} [scope] The execution scope (`this`) of the callback function.
29521 * @member Ext
29522 * @method require
29523 */\r
29524 Ext.require = alias(Loader, 'require');\r
29525 /**
29526 * Synchronously loads all classes by the given names and all their direct dependencies; optionally
29527 * executes the given callback function when finishes, within the optional scope.
29528 *
29529 * @param {String/String[]} expressions The class, classes or wildcards to load.
29530 * @param {Function} [fn] The callback function.
29531 * @param {Object} [scope] The execution scope (`this`) of the callback function.
29532 * @member Ext
29533 * @method syncRequire
29534 */\r
29535 Ext.syncRequire = alias(Loader, 'syncRequire');\r
29536 /**
29537 * Explicitly exclude files from being loaded. Useful when used in conjunction with a
29538 * broad include expression. Can be chained with more `require` and `exclude` methods,
29539 * for example:
29540 *
29541 * Ext.exclude('Ext.data.*').require('*');
29542 *
29543 * Ext.exclude('widget.button*').require('widget.*');
29544 *
29545 * @param {String/String[]} excludes
29546 * @return {Object} Contains `exclude`, `require` and `syncRequire` methods for chaining.
29547 * @member Ext
29548 * @method exclude
29549 */\r
29550 Ext.exclude = alias(Loader, 'exclude');\r
29551 /**
29552 * @cfg {String[]} requires
29553 * @member Ext.Class
29554 * List of classes that have to be loaded before instantiating this class.
29555 * For example:
29556 *
29557 * Ext.define('Mother', {
29558 * requires: ['Child'],
29559 * giveBirth: function() {
29560 * // we can be sure that child class is available.
29561 * return new Child();
29562 * }
29563 * });
29564 */\r
29565 Class.registerPreprocessor('loader', function(cls, data, hooks, continueFn) {\r
29566 Ext.classSystemMonitor && Ext.classSystemMonitor(cls, 'Ext.Loader#loaderPreprocessor', arguments);\r
29567 // jshint ignore:line\r
29568 var me = this,\r
29569 dependencies = [],\r
29570 dependency,\r
29571 className = Manager.getName(cls),\r
29572 i, j, ln, subLn, value, propertyName, propertyValue, requiredMap;\r
29573 /*
29574 Loop through the dependencyProperties, look for string class names and push
29575 them into a stack, regardless of whether the property's value is a string, array or object. For example:
29576 {
29577 extend: 'Ext.MyClass',
29578 requires: ['Ext.some.OtherClass'],
29579 mixins: {
29580 thing: 'Foo.bar.Thing';
29581 }
29582 }
29583 which will later be transformed into:
29584 {
29585 extend: Ext.MyClass,
29586 requires: [Ext.some.OtherClass],
29587 mixins: {
29588 thing: Foo.bar.Thing;
29589 }
29590 }
29591 */\r
29592 for (i = 0 , ln = dependencyProperties.length; i < ln; i++) {\r
29593 propertyName = dependencyProperties[i];\r
29594 if (data.hasOwnProperty(propertyName)) {\r
29595 propertyValue = data[propertyName];\r
29596 if (typeof propertyValue === 'string') {\r
29597 dependencies.push(propertyValue);\r
29598 } else if (propertyValue instanceof Array) {\r
29599 for (j = 0 , subLn = propertyValue.length; j < subLn; j++) {\r
29600 value = propertyValue[j];\r
29601 if (typeof value === 'string') {\r
29602 dependencies.push(value);\r
29603 }\r
29604 }\r
29605 } else if (typeof propertyValue !== 'function') {\r
29606 for (j in propertyValue) {\r
29607 if (propertyValue.hasOwnProperty(j)) {\r
29608 value = propertyValue[j];\r
29609 if (typeof value === 'string') {\r
29610 dependencies.push(value);\r
29611 }\r
29612 }\r
29613 }\r
29614 }\r
29615 }\r
29616 }\r
29617 if (dependencies.length === 0) {\r
29618 return;\r
29619 }\r
29620 if (className) {\r
29621 _requiresMap[className] = dependencies;\r
29622 }\r
29623 var deadlockPath = [],\r
29624 detectDeadlock;\r
29625 /*
29626 Automatically detect deadlocks before-hand,
29627 will throw an error with detailed path for ease of debugging. Examples of deadlock cases:
29628
29629 - A extends B, then B extends A
29630 - A requires B, B requires C, then C requires A
29631
29632 The detectDeadlock function will recursively transverse till the leaf, hence it can detect deadlocks
29633 no matter how deep the path is.
29634 */\r
29635 if (className) {\r
29636 requiredMap = Loader.requiredByMap || (Loader.requiredByMap = {});\r
29637 for (i = 0 , ln = dependencies.length; i < ln; i++) {\r
29638 dependency = dependencies[i];\r
29639 (requiredMap[dependency] || (requiredMap[dependency] = [])).push(className);\r
29640 }\r
29641 detectDeadlock = function(cls) {\r
29642 deadlockPath.push(cls);\r
29643 if (_requiresMap[cls]) {\r
29644 if (Ext.Array.contains(_requiresMap[cls], className)) {\r
29645 Ext.raise("Circular requirement detected! '" + className + "' and '" + deadlockPath[1] + "' mutually require each other. Path: " + deadlockPath.join(' -> ') + " -> " + deadlockPath[0]);\r
29646 }\r
29647 for (i = 0 , ln = _requiresMap[cls].length; i < ln; i++) {\r
29648 detectDeadlock(_requiresMap[cls][i]);\r
29649 }\r
29650 }\r
29651 };\r
29652 detectDeadlock(className);\r
29653 }\r
29654 (className ? Loader.exclude(className) : Loader).require(dependencies, function() {\r
29655 for (i = 0 , ln = dependencyProperties.length; i < ln; i++) {\r
29656 propertyName = dependencyProperties[i];\r
29657 if (data.hasOwnProperty(propertyName)) {\r
29658 propertyValue = data[propertyName];\r
29659 if (typeof propertyValue === 'string') {\r
29660 data[propertyName] = Manager.get(propertyValue);\r
29661 } else if (propertyValue instanceof Array) {\r
29662 for (j = 0 , subLn = propertyValue.length; j < subLn; j++) {\r
29663 value = propertyValue[j];\r
29664 if (typeof value === 'string') {\r
29665 data[propertyName][j] = Manager.get(value);\r
29666 }\r
29667 }\r
29668 } else if (typeof propertyValue !== 'function') {\r
29669 for (var k in propertyValue) {\r
29670 if (propertyValue.hasOwnProperty(k)) {\r
29671 value = propertyValue[k];\r
29672 if (typeof value === 'string') {\r
29673 data[propertyName][k] = Manager.get(value);\r
29674 }\r
29675 }\r
29676 }\r
29677 }\r
29678 }\r
29679 }\r
29680 continueFn.call(me, cls, data, hooks);\r
29681 });\r
29682 return false;\r
29683 }, true, 'after', 'className');\r
29684 /**
29685 * @cfg {String[]} uses
29686 * @member Ext.Class
29687 * List of optional classes to load together with this class. These aren't neccessarily loaded before
29688 * this class is created, but are guaranteed to be available before Ext.onReady listeners are
29689 * invoked. For example:
29690 *
29691 * Ext.define('Mother', {
29692 * uses: ['Child'],
29693 * giveBirth: function() {
29694 * // This code might, or might not work:
29695 * // return new Child();
29696 *
29697 * // Instead use Ext.create() to load the class at the spot if not loaded already:
29698 * return Ext.create('Child');
29699 * }
29700 * });
29701 */\r
29702 Manager.registerPostprocessor('uses', function(name, cls, data) {\r
29703 Ext.classSystemMonitor && Ext.classSystemMonitor(cls, 'Ext.Loader#usesPostprocessor', arguments);\r
29704 // jshint ignore:line\r
29705 var manifest = Ext.manifest,\r
29706 loadOrder = manifest && manifest.loadOrder,\r
29707 classes = manifest && manifest.classes,\r
29708 uses, clazz, item, len, i, indexMap;\r
29709 if (loadOrder) {\r
29710 clazz = classes[name];\r
29711 if (clazz && !isNaN(i = clazz.idx)) {\r
29712 item = loadOrder[i];\r
29713 uses = item.uses;\r
29714 indexMap = {};\r
29715 for (len = uses.length , i = 0; i < len; i++) {\r
29716 indexMap[uses[i]] = true;\r
29717 }\r
29718 uses = Ext.Boot.getPathsFromIndexes(indexMap, loadOrder, true);\r
29719 if (uses.length > 0) {\r
29720 Loader.loadScripts({\r
29721 url: uses,\r
29722 sequential: true\r
29723 });\r
29724 }\r
29725 }\r
29726 }\r
29727 if (data.uses) {\r
29728 uses = data.uses;\r
29729 Loader.addUsedClasses(uses);\r
29730 }\r
29731 });\r
29732 Manager.onCreated(Loader.historyPush);\r
29733 Loader.init();\r
29734}());\r
29735//-----------------------------------------------------------------------------\r
29736// Use performance.now when available to keep timestamps consistent.\r
29737Ext._endTime = Ext.ticks();\r
29738// This hook is to allow tools like DynaTrace to deterministically detect the availability\r
29739// of Ext.onReady. Since Loader takes over Ext.onReady this must be done here and not in\r
29740// Ext.env.Ready.\r
29741if (Ext._beforereadyhandler) {\r
29742 Ext._beforereadyhandler();\r
29743}\r
29744\r
29745/** */\r
29746Ext.define('Ext.overrides.util.Positionable', {\r
29747 override: 'Ext.util.Positionable',\r
29748 /**
29749 * @method alignTo
29750 * @param {Ext.util.Positionable/HTMLElement/String} anchorToEl The Positionable,
29751 * HTMLElement, or id of the element to align to.
29752 * @param {String} [alignment="tl-bl?"] The position to align to
29753 * @param {Number[]} [offsets] Offset the positioning by [x, y]
29754 * @param {Boolean/Object} [animate] true for the default animation or a standard
29755 * Element animation config object
29756 * @return {Ext.util.Positionable} this
29757 */\r
29758 /**
29759 * @method anchorTo
29760 * Anchors an element to another element and realigns it when the window is resized.
29761 * @param {Ext.util.Positionable/HTMLElement/String} anchorToEl The Positionable,
29762 * HTMLElement, or id of the element to align to.
29763 * @param {String} [alignment="tl-bl?"] The position to align to
29764 * @param {Number[]} [offsets] Offset the positioning by [x, y]
29765 * @param {Boolean/Object} [animate] true for the default animation or a standard
29766 * Element animation config object
29767 * @param {Boolean/Number} [monitorScroll=50] True to monitor body scroll and
29768 * reposition. If this parameter is a number, it is used as the buffer delay in
29769 * milliseconds.
29770 * @param {Function} [callback] The function to call after the animation finishes
29771 * @return {Ext.util.Positionable} this
29772 */\r
29773 anchorTo: function(anchorToEl, alignment, offsets, animate, monitorScroll, callback) {\r
29774 var me = this,\r
29775 scroll = !Ext.isEmpty(monitorScroll),\r
29776 action = function() {\r
29777 me.alignTo(anchorToEl, alignment, offsets, animate);\r
29778 Ext.callback(callback, me);\r
29779 },\r
29780 anchor = me.getAnchor();\r
29781 // previous listener anchor, remove it\r
29782 me.removeAnchor();\r
29783 Ext.apply(anchor, {\r
29784 fn: action,\r
29785 scroll: scroll\r
29786 });\r
29787 Ext.on('resize', action, null);\r
29788 if (scroll) {\r
29789 Ext.getWin().on('scroll', action, null, {\r
29790 buffer: !isNaN(monitorScroll) ? monitorScroll : 50\r
29791 });\r
29792 }\r
29793 action();\r
29794 // align immediately\r
29795 return me;\r
29796 },\r
29797 getAnchor: function() {\r
29798 var el = this.el,\r
29799 data, anchor;\r
29800 if (!el.dom) {\r
29801 return;\r
29802 }\r
29803 data = el.getData();\r
29804 anchor = data._anchor;\r
29805 if (!anchor) {\r
29806 anchor = data._anchor = {};\r
29807 }\r
29808 return anchor;\r
29809 },\r
29810 /**
29811 * @method move
29812 * Move the element relative to its current position.
29813 * @param {String} direction Possible values are:
29814 *
29815 * - `"l"` (or `"left"`)
29816 * - `"r"` (or `"right"`)
29817 * - `"t"` (or `"top"`, or `"up"`)
29818 * - `"b"` (or `"bottom"`, or `"down"`)
29819 *
29820 * @param {Number} distance How far to move the element in pixels
29821 * @param {Boolean/Object} [animate] true for the default animation or a standard
29822 * Element animation config object
29823 */\r
29824 /**
29825 * Remove any anchor to this element. See {@link #anchorTo}.
29826 * @return {Ext.util.Positionable} this
29827 */\r
29828 removeAnchor: function() {\r
29829 var anchor = this.getAnchor();\r
29830 if (anchor && anchor.fn) {\r
29831 Ext.un('resize', anchor.fn);\r
29832 if (anchor.scroll) {\r
29833 Ext.getWin().on('scroll', anchor.fn);\r
29834 }\r
29835 delete anchor.fn;\r
29836 }\r
29837 return this;\r
29838 },\r
29839 /**
29840 * @method setBox
29841 * Sets the element's box. If animate is true then x, y, width, and height will be
29842 * animated concurrently.
29843 * @param {Object} box The box to fill {x, y, width, height}
29844 * @param {Boolean/Object} [animate] true for the default animation or a standard
29845 * Element animation config object
29846 * @return {Ext.util.Positionable} this
29847 */\r
29848 setBox: function(box, animate) {\r
29849 var me = this;\r
29850 if (box.isRegion) {\r
29851 box = {\r
29852 x: box.left,\r
29853 y: box.top,\r
29854 width: box.right - box.left,\r
29855 height: box.bottom - box.top\r
29856 };\r
29857 }\r
29858 if (animate) {\r
29859 me.constrainBox(box);\r
29860 me.animate(Ext.applyIf({\r
29861 to: box,\r
29862 listeners: {\r
29863 afteranimate: Ext.Function.bind(me.afterSetPosition, me, [\r
29864 box.x,\r
29865 box.y\r
29866 ])\r
29867 }\r
29868 }, animate));\r
29869 } else {\r
29870 me.callParent([\r
29871 box\r
29872 ]);\r
29873 }\r
29874 return me;\r
29875 }\r
29876});\r
29877/**
29878 * @method setX
29879 * Sets the X position of the DOM element based on page coordinates.
29880 * @param {Number} x The X position
29881 * @param {Boolean/Object} [animate] True for the default animation, or a standard
29882 * Element animation config object
29883 * @return {Ext.util.Positionable} this
29884 */\r
29885/**
29886 * @method setXY
29887 * Sets the position of the DOM element in page coordinates.
29888 * @param {Number[]} pos Contains X & Y [x, y] values for new position (coordinates
29889 * are page-based)
29890 * @param {Boolean/Object} [animate] True for the default animation, or a standard
29891 * Element animation config object
29892 * @return {Ext.util.Positionable} this
29893 */\r
29894/**
29895 * @method setY
29896 * Sets the Y position of the DOM element based on page coordinates.
29897 * @param {Number} y The Y position
29898 * @param {Boolean/Object} [animate] True for the default animation, or a standard
29899 * Element animation config object
29900 * @return {Ext.util.Positionable} this
29901 */\r
29902\r
29903/**
29904 *
29905 */\r
29906Ext.define('Ext.overrides.event.Event', {\r
29907 override: 'Ext.event.Event',\r
29908 // map of events that should fire global mousedown even if stopped\r
29909 mousedownEvents: {\r
29910 mousedown: 1,\r
29911 pointerdown: 1,\r
29912 touchstart: 1\r
29913 },\r
29914 /**
29915 * @method injectEvent
29916 * @member Ext.event.Event
29917 * Injects a DOM event using the data in this object and (optionally) a new target.
29918 * This is a low-level technique and not likely to be used by application code. The
29919 * currently supported event types are:
29920 * <p><b>HTMLEvents</b></p>
29921 * <ul>
29922 * <li>load</li>
29923 * <li>unload</li>
29924 * <li>select</li>
29925 * <li>change</li>
29926 * <li>submit</li>
29927 * <li>reset</li>
29928 * <li>resize</li>
29929 * <li>scroll</li>
29930 * </ul>
29931 * <p><b>MouseEvents</b></p>
29932 * <ul>
29933 * <li>click</li>
29934 * <li>dblclick</li>
29935 * <li>mousedown</li>
29936 * <li>mouseup</li>
29937 * <li>mouseover</li>
29938 * <li>mousemove</li>
29939 * <li>mouseout</li>
29940 * </ul>
29941 * <p><b>UIEvents</b></p>
29942 * <ul>
29943 * <li>focusin</li>
29944 * <li>focusout</li>
29945 * <li>activate</li>
29946 * <li>focus</li>
29947 * <li>blur</li>
29948 * </ul>
29949 * @param {Ext.Element/HTMLElement} target (optional) If specified, the target for the event. This
29950 * is likely to be used when relaying a DOM event. If not specified, {@link #getTarget}
29951 * is used to determine the target.
29952 */\r
29953 injectEvent: (function() {\r
29954 var API,\r
29955 dispatchers = {},\r
29956 // keyed by event type (e.g., 'mousedown')\r
29957 crazyIEButtons;\r
29958 // Good reference: http://developer.yahoo.com/yui/docs/UserAction.js.html\r
29959 // IE9 has createEvent, but this code causes major problems with htmleditor (it\r
29960 // blocks all mouse events and maybe more). TODO\r
29961 if (!Ext.isIE9m && document.createEvent) {\r
29962 // if (DOM compliant)\r
29963 API = {\r
29964 createHtmlEvent: function(doc, type, bubbles, cancelable) {\r
29965 var event = doc.createEvent('HTMLEvents');\r
29966 event.initEvent(type, bubbles, cancelable);\r
29967 return event;\r
29968 },\r
29969 createMouseEvent: function(doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) {\r
29970 var event = doc.createEvent('MouseEvents'),\r
29971 view = doc.defaultView || window;\r
29972 if (event.initMouseEvent) {\r
29973 event.initMouseEvent(type, bubbles, cancelable, view, detail, clientX, clientY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget);\r
29974 } else {\r
29975 // old Safari\r
29976 event = doc.createEvent('UIEvents');\r
29977 event.initEvent(type, bubbles, cancelable);\r
29978 event.view = view;\r
29979 event.detail = detail;\r
29980 event.screenX = clientX;\r
29981 event.screenY = clientY;\r
29982 event.clientX = clientX;\r
29983 event.clientY = clientY;\r
29984 event.ctrlKey = ctrlKey;\r
29985 event.altKey = altKey;\r
29986 event.metaKey = metaKey;\r
29987 event.shiftKey = shiftKey;\r
29988 event.button = button;\r
29989 event.relatedTarget = relatedTarget;\r
29990 }\r
29991 return event;\r
29992 },\r
29993 createUIEvent: function(doc, type, bubbles, cancelable, detail) {\r
29994 var event = doc.createEvent('UIEvents'),\r
29995 view = doc.defaultView || window;\r
29996 event.initUIEvent(type, bubbles, cancelable, view, detail);\r
29997 return event;\r
29998 },\r
29999 fireEvent: function(target, type, event) {\r
30000 target.dispatchEvent(event);\r
30001 }\r
30002 };\r
30003 } else if (document.createEventObject) {\r
30004 // else if (IE)\r
30005 crazyIEButtons = {\r
30006 0: 1,\r
30007 1: 4,\r
30008 2: 2\r
30009 };\r
30010 API = {\r
30011 createHtmlEvent: function(doc, type, bubbles, cancelable) {\r
30012 var event = doc.createEventObject();\r
30013 event.bubbles = bubbles;\r
30014 event.cancelable = cancelable;\r
30015 return event;\r
30016 },\r
30017 createMouseEvent: function(doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) {\r
30018 var event = doc.createEventObject();\r
30019 event.bubbles = bubbles;\r
30020 event.cancelable = cancelable;\r
30021 event.detail = detail;\r
30022 event.screenX = clientX;\r
30023 event.screenY = clientY;\r
30024 event.clientX = clientX;\r
30025 event.clientY = clientY;\r
30026 event.ctrlKey = ctrlKey;\r
30027 event.altKey = altKey;\r
30028 event.shiftKey = shiftKey;\r
30029 event.metaKey = metaKey;\r
30030 event.button = crazyIEButtons[button] || button;\r
30031 event.relatedTarget = relatedTarget;\r
30032 // cannot assign to/fromElement\r
30033 return event;\r
30034 },\r
30035 createUIEvent: function(doc, type, bubbles, cancelable, detail) {\r
30036 var event = doc.createEventObject();\r
30037 event.bubbles = bubbles;\r
30038 event.cancelable = cancelable;\r
30039 return event;\r
30040 },\r
30041 fireEvent: function(target, type, event) {\r
30042 target.fireEvent('on' + type, event);\r
30043 }\r
30044 };\r
30045 }\r
30046 //----------------\r
30047 // HTMLEvents\r
30048 Ext.Object.each({\r
30049 load: [\r
30050 false,\r
30051 false\r
30052 ],\r
30053 unload: [\r
30054 false,\r
30055 false\r
30056 ],\r
30057 select: [\r
30058 true,\r
30059 false\r
30060 ],\r
30061 change: [\r
30062 true,\r
30063 false\r
30064 ],\r
30065 submit: [\r
30066 true,\r
30067 true\r
30068 ],\r
30069 reset: [\r
30070 true,\r
30071 false\r
30072 ],\r
30073 resize: [\r
30074 true,\r
30075 false\r
30076 ],\r
30077 scroll: [\r
30078 true,\r
30079 false\r
30080 ]\r
30081 }, function(name, value) {\r
30082 var bubbles = value[0],\r
30083 cancelable = value[1];\r
30084 dispatchers[name] = function(targetEl, srcEvent) {\r
30085 var e = API.createHtmlEvent(name, bubbles, cancelable);\r
30086 API.fireEvent(targetEl, name, e);\r
30087 };\r
30088 });\r
30089 //----------------\r
30090 // MouseEvents\r
30091 function createMouseEventDispatcher(type, detail) {\r
30092 var cancelable = (type !== 'mousemove');\r
30093 return function(targetEl, srcEvent) {\r
30094 var xy = srcEvent.getXY(),\r
30095 e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable, detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button, srcEvent.relatedTarget);\r
30096 API.fireEvent(targetEl, type, e);\r
30097 };\r
30098 }\r
30099 Ext.each([\r
30100 'click',\r
30101 'dblclick',\r
30102 'mousedown',\r
30103 'mouseup',\r
30104 'mouseover',\r
30105 'mousemove',\r
30106 'mouseout'\r
30107 ], function(eventName) {\r
30108 dispatchers[eventName] = createMouseEventDispatcher(eventName, 1);\r
30109 });\r
30110 //----------------\r
30111 // UIEvents\r
30112 Ext.Object.each({\r
30113 focusin: [\r
30114 true,\r
30115 false\r
30116 ],\r
30117 focusout: [\r
30118 true,\r
30119 false\r
30120 ],\r
30121 activate: [\r
30122 true,\r
30123 true\r
30124 ],\r
30125 focus: [\r
30126 false,\r
30127 false\r
30128 ],\r
30129 blur: [\r
30130 false,\r
30131 false\r
30132 ]\r
30133 }, function(name, value) {\r
30134 var bubbles = value[0],\r
30135 cancelable = value[1];\r
30136 dispatchers[name] = function(targetEl, srcEvent) {\r
30137 var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1);\r
30138 API.fireEvent(targetEl, name, e);\r
30139 };\r
30140 });\r
30141 //---------\r
30142 if (!API) {\r
30143 // not even sure what ancient browsers fall into this category...\r
30144 dispatchers = {};\r
30145 // never mind all those we just built :P\r
30146 API = {};\r
30147 }\r
30148 function cannotInject(target, srcEvent) {}\r
30149 // TODO log something\r
30150 return function(target) {\r
30151 var me = this,\r
30152 dispatcher = dispatchers[me.type] || cannotInject,\r
30153 t = target ? (target.dom || target) : me.getTarget();\r
30154 dispatcher(t, me);\r
30155 };\r
30156 }()),\r
30157 // call to produce method\r
30158 preventDefault: function() {\r
30159 var me = this,\r
30160 event = me.browserEvent,\r
30161 parentEvent = me.parentEvent,\r
30162 unselectable, target;\r
30163 // This check is for IE8/9. The event object may have been\r
30164 // invalidated, so we can't delve into the details of it. If so,\r
30165 // just fall out gracefully and don't attempt to do anything.\r
30166 if (typeof event.type !== 'unknown') {\r
30167 me.defaultPrevented = true;\r
30168 // if the event was created by prototype-chaining a new object to an existing event\r
30169 // instance, we need to make sure the parent event is defaultPrevented as well.\r
30170 if (parentEvent) {\r
30171 parentEvent.defaultPrevented = true;\r
30172 }\r
30173 if (event.preventDefault) {\r
30174 event.preventDefault();\r
30175 } else {\r
30176 // The purpose of the code below is for preventDefault to stop focus from\r
30177 // occurring like it does in other modern browsers. This only happens in\r
30178 // IE8/9 when using attachEvent. The use of unselectable seems the most reliable\r
30179 // way to prevent this from happening. We need to use a timeout to restore the\r
30180 // unselectable state because if we don't setting it has no effect. It's important\r
30181 // to set the atrribute to 'on' as opposed to just setting the property on the DOM element.\r
30182 // See the link below for a discussion on the issue:\r
30183 // http://bugs.jquery.com/ticket/10345\r
30184 if (event.type === 'mousedown') {\r
30185 target = event.target;\r
30186 unselectable = target.getAttribute('unselectable');\r
30187 if (unselectable !== 'on') {\r
30188 target.setAttribute('unselectable', 'on');\r
30189 Ext.defer(function() {\r
30190 target.setAttribute('unselectable', unselectable);\r
30191 }, 1);\r
30192 }\r
30193 }\r
30194 // IE9 and earlier do not support preventDefault\r
30195 event.returnValue = false;\r
30196 // Some keys events require setting the keyCode to -1 to be prevented\r
30197 // all ctrl + X and F1 -> F12\r
30198 if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {\r
30199 event.keyCode = -1;\r
30200 }\r
30201 }\r
30202 }\r
30203 return me;\r
30204 },\r
30205 stopPropagation: function() {\r
30206 var me = this,\r
30207 event = me.browserEvent;\r
30208 // This check is for IE8/9. The event object may have been\r
30209 // invalidated, so we can't delve into the details of it. If so,\r
30210 // just fall out gracefully and don't attempt to do anything.\r
30211 if (typeof event.type !== 'unknown') {\r
30212 if (me.mousedownEvents[me.type]) {\r
30213 // Fire the "unstoppable" global mousedown event\r
30214 // (used for menu hiding, etc)\r
30215 Ext.GlobalEvents.fireMouseDown(me);\r
30216 }\r
30217 me.callParent();\r
30218 }\r
30219 return me;\r
30220 },\r
30221 deprecated: {\r
30222 '5.0': {\r
30223 methods: {\r
30224 /**
30225 * @method clone
30226 * @member Ext.event.Event
30227 * Clones this event.
30228 * @return {Ext.event.Event} The cloned copy
30229 * @deprecated 5.0.0
30230 */\r
30231 clone: function() {\r
30232 return new this.self(this.browserEvent, this);\r
30233 }\r
30234 }\r
30235 }\r
30236 }\r
30237}, function() {\r
30238 var Event = this,\r
30239 btnMap,\r
30240 onKeyDown = function(e) {\r
30241 if (e.keyCode === 9) {\r
30242 Event.forwardTab = !e.shiftKey;\r
30243 }\r
30244 },\r
30245 onKeyUp = function(e) {\r
30246 if (e.keyCode === 9) {\r
30247 delete Event.forwardTab;\r
30248 }\r
30249 };\r
30250 if (Ext.isIE9m) {\r
30251 btnMap = {\r
30252 0: 0,\r
30253 1: 0,\r
30254 4: 1,\r
30255 2: 2\r
30256 };\r
30257 Event.override({\r
30258 statics: {\r
30259 /**
30260 * @member Ext.event.Event
30261 * When events are attached using IE's attachEvent API instead of
30262 * addEventListener accessing any members of an event object asynchronously
30263 * results in "Member not found" error. To work around this we fabricate
30264 * our own event object by copying all of its members to a new object.
30265 * @param {Event} browserEvent The native browser event object
30266 * @private
30267 * @static
30268 */\r
30269 enableIEAsync: function(browserEvent) {\r
30270 var name,\r
30271 fakeEvent = {};\r
30272 for (name in browserEvent) {\r
30273 fakeEvent[name] = browserEvent[name];\r
30274 }\r
30275 return fakeEvent;\r
30276 }\r
30277 },\r
30278 constructor: function(event, info, touchesMap, identifiers) {\r
30279 var me = this;\r
30280 me.callParent([\r
30281 event,\r
30282 info,\r
30283 touchesMap,\r
30284 identifiers\r
30285 ]);\r
30286 me.button = btnMap[event.button];\r
30287 if (event.type === 'contextmenu') {\r
30288 me.button = 2;\r
30289 }\r
30290 // IE8/9 reports click as 0, so we can at least attempt to infer here\r
30291 // IE8 can throw an error when trying to access properties on a browserEvent\r
30292 // object when the event has been buffered or delayed. Cache them here\r
30293 // so we can access them later.\r
30294 me.toElement = event.toElement;\r
30295 me.fromElement = event.fromElement;\r
30296 },\r
30297 mouseLeaveRe: /(mouseout|mouseleave)/,\r
30298 mouseEnterRe: /(mouseover|mouseenter)/,\r
30299 /**
30300 * @member Ext.event.Event
30301 * @inheritdoc Ext.event.Event#static-enableIEAsync
30302 * @private
30303 */\r
30304 enableIEAsync: function(browserEvent) {\r
30305 this.browserEvent = this.self.enableIEAsync(browserEvent);\r
30306 },\r
30307 getRelatedTarget: function(selector, maxDepth, returnEl) {\r
30308 var me = this,\r
30309 type, target;\r
30310 if (!me.relatedTarget) {\r
30311 type = me.type;\r
30312 if (me.mouseLeaveRe.test(type)) {\r
30313 target = me.toElement;\r
30314 } else if (me.mouseEnterRe.test(type)) {\r
30315 target = me.fromElement;\r
30316 }\r
30317 if (target) {\r
30318 me.relatedTarget = me.self.resolveTextNode(target);\r
30319 }\r
30320 }\r
30321 return me.callParent([\r
30322 selector,\r
30323 maxDepth,\r
30324 returnEl\r
30325 ]);\r
30326 }\r
30327 });\r
30328 // We place these listeners to capture Tab and Shift-Tab key strokes\r
30329 // and pass this information in the focus/blur event if it happens\r
30330 // between keydown/keyup pair.\r
30331 document.attachEvent('onkeydown', onKeyDown);\r
30332 document.attachEvent('onkeyup', onKeyUp);\r
30333 window.attachEvent('onunload', function() {\r
30334 document.detachEvent('onkeydown', onKeyDown);\r
30335 document.detachEvent('onkeyup', onKeyUp);\r
30336 });\r
30337 } else if (document.addEventListener) {\r
30338 document.addEventListener('keydown', onKeyDown, true);\r
30339 document.addEventListener('keyup', onKeyUp, true);\r
30340 }\r
30341});\r
30342\r
30343Ext.define('Ext.overrides.event.publisher.Dom', {\r
30344 override: 'Ext.event.publisher.Dom'\r
30345}, function(DomPublisher) {\r
30346 if (Ext.isIE9m) {\r
30347 var docElement = document.documentElement,\r
30348 docBody = document.body,\r
30349 prototype = DomPublisher.prototype,\r
30350 onDirectEvent, onDirectCaptureEvent;\r
30351 prototype.target = document;\r
30352 prototype.directBoundListeners = {};\r
30353 // This method gets bound to the element scope in addDirectListener so that\r
30354 // the currentTarget can be captured using "this".\r
30355 onDirectEvent = function(e, publisher, capture) {\r
30356 e.target = e.srcElement || window;\r
30357 e.currentTarget = this;\r
30358 if (capture) {\r
30359 // Although directly attached capture listeners are not supported in IE9m\r
30360 // we still need to call the handler so at least the event fires.\r
30361 publisher.onDirectCaptureEvent(e);\r
30362 } else {\r
30363 publisher.onDirectEvent(e);\r
30364 }\r
30365 };\r
30366 onDirectCaptureEvent = function(e, publisher) {\r
30367 e.target = e.srcElement || window;\r
30368 e.currentTarget = this;\r
30369 // this, not DomPublisher\r
30370 publisher.onDirectCaptureEvent(e);\r
30371 };\r
30372 DomPublisher.override({\r
30373 addDelegatedListener: function(eventName) {\r
30374 this.delegatedListeners[eventName] = 1;\r
30375 // Use attachEvent for IE9 and below. Even though IE9 strict supports\r
30376 // addEventListener, it has issues with using synthetic events.\r
30377 this.target.attachEvent('on' + eventName, this.onDelegatedEvent);\r
30378 },\r
30379 removeDelegatedListener: function(eventName) {\r
30380 delete this.delegatedListeners[eventName];\r
30381 this.target.detachEvent('on' + eventName, this.onDelegatedEvent);\r
30382 },\r
30383 addDirectListener: function(eventName, element, capture) {\r
30384 var me = this,\r
30385 dom = element.dom,\r
30386 // binding the listener to the element allows us to capture the\r
30387 // "currentTarget" (see onDirectEvent)\r
30388 boundFn = Ext.Function.bind(onDirectEvent, dom, [\r
30389 me,\r
30390 capture\r
30391 ], true),\r
30392 directBoundListeners = me.directBoundListeners,\r
30393 handlers = directBoundListeners[eventName] || (directBoundListeners[eventName] = {});\r
30394 handlers[dom.id] = boundFn;\r
30395 // may be called with an SVG element here, which\r
30396 // does not have the attachEvent method on IE 9 strict\r
30397 if (dom.attachEvent) {\r
30398 dom.attachEvent('on' + eventName, boundFn);\r
30399 } else {\r
30400 me.callParent(arguments);\r
30401 }\r
30402 },\r
30403 removeDirectListener: function(eventName, element) {\r
30404 var dom = element.dom;\r
30405 if (dom.detachEvent) {\r
30406 dom.detachEvent('on' + eventName, this.directBoundListeners[eventName][dom.id]);\r
30407 } else {\r
30408 this.callParent(arguments);\r
30409 }\r
30410 },\r
30411 doDelegatedEvent: function(e, invokeAfter) {\r
30412 e.target = e.srcElement || window;\r
30413 if (e.type === 'focusin') {\r
30414 // IE8 sometimes happen to focus <html> element instead of the body\r
30415 e.relatedTarget = e.fromElement === docBody || e.fromElement === docElement ? null : e.fromElement;\r
30416 } else if (e.type === 'focusout') {\r
30417 e.relatedTarget = e.toElement === docBody || e.toElement === docElement ? null : e.toElement;\r
30418 }\r
30419 return this.callParent([\r
30420 e,\r
30421 invokeAfter\r
30422 ]);\r
30423 }\r
30424 });\r
30425 // can't capture any events without addEventListener. Have to have direct\r
30426 // listeners for every event that does not bubble.\r
30427 Ext.apply(prototype.directEvents, prototype.captureEvents);\r
30428 // These do not bubble in IE9m so have to attach direct listeners as well.\r
30429 Ext.apply(prototype.directEvents, {\r
30430 change: 1,\r
30431 input: 1,\r
30432 paste: 1\r
30433 });\r
30434 prototype.captureEvents = {};\r
30435 }\r
30436});\r
30437\r
30438Ext.define('Ext.overrides.event.publisher.Gesture', {\r
30439 override: 'Ext.event.publisher.Gesture'\r
30440}, function() {\r
30441 if (Ext.isIE9m) {\r
30442 this.override({\r
30443 updateTouches: function(e, isEnd) {\r
30444 var browserEvent = e.browserEvent,\r
30445 xy = e.getXY();\r
30446 // I don't always set pageX and pageY on the event object, but when I do\r
30447 // it's because the Gesture publisher expects an event object that has them.\r
30448 browserEvent.pageX = xy[0];\r
30449 browserEvent.pageY = xy[1];\r
30450 this.callParent([\r
30451 e,\r
30452 isEnd\r
30453 ]);\r
30454 },\r
30455 doDelegatedEvent: function(e) {\r
30456 // Workaround IE's "Member not found" errors when accessing an event\r
30457 // object asynchronously. Needed for all gesture handlers because\r
30458 // they use requestAnimationFrame (see enableIEAsync for more details)\r
30459 this.callParent([\r
30460 Ext.event.Event.enableIEAsync(e)\r
30461 ]);\r
30462 }\r
30463 });\r
30464 }\r
30465});\r
30466\r
30467/**
30468 * @class Ext.dom.Element
30469 * @override Ext.dom.Element
30470 */\r
30471Ext.define('Ext.overrides.dom.Element', (function() {\r
30472 var Element,\r
30473 // we cannot do this yet "= Ext.dom.Element"\r
30474 WIN = window,\r
30475 DOC = document,\r
30476 HIDDEN = 'hidden',\r
30477 ISCLIPPED = 'isClipped',\r
30478 OVERFLOW = 'overflow',\r
30479 OVERFLOWX = 'overflow-x',\r
30480 OVERFLOWY = 'overflow-y',\r
30481 ORIGINALCLIP = 'originalClip',\r
30482 HEIGHT = 'height',\r
30483 WIDTH = 'width',\r
30484 VISIBILITY = 'visibility',\r
30485 DISPLAY = 'display',\r
30486 NONE = 'none',\r
30487 OFFSETS = 'offsets',\r
30488 CLIP = 'clip',\r
30489 ORIGINALDISPLAY = 'originalDisplay',\r
30490 VISMODE = 'visibilityMode',\r
30491 ISVISIBLE = 'isVisible',\r
30492 OFFSETCLASS = Ext.baseCSSPrefix + 'hidden-offsets',\r
30493 CLIPCLASS = Ext.baseCSSPrefix + 'hidden-clip',\r
30494 boxMarkup = [\r
30495 '<div class="{0}-tl" role="presentation">',\r
30496 '<div class="{0}-tr" role="presentation">',\r
30497 '<div class="{0}-tc" role="presentation"></div>',\r
30498 '</div>',\r
30499 '</div>',\r
30500 '<div class="{0}-ml" role="presentation">',\r
30501 '<div class="{0}-mr" role="presentation">',\r
30502 '<div class="{0}-mc" role="presentation"></div>',\r
30503 '</div>',\r
30504 '</div>',\r
30505 '<div class="{0}-bl" role="presentation">',\r
30506 '<div class="{0}-br" role="presentation">',\r
30507 '<div class="{0}-bc" role="presentation"></div>',\r
30508 '</div>',\r
30509 '</div>'\r
30510 ].join(''),\r
30511 scriptTagRe = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
30512 replaceScriptTagRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,\r
30513 srcRe = /\ssrc=([\'\"])(.*?)\1/i,\r
30514 nonSpaceRe = /\S/,\r
30515 typeRe = /\stype=([\'\"])(.*?)\1/i,\r
30516 msRe = /^-ms-/,\r
30517 camelRe = /(-[a-z])/gi,\r
30518 camelReplaceFn = function(m, a) {\r
30519 return a.charAt(1).toUpperCase();\r
30520 },\r
30521 XMASKED = Ext.baseCSSPrefix + "masked",\r
30522 XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",\r
30523 EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",\r
30524 bodyRe = /^body/i,\r
30525 propertyCache = {},\r
30526 getVisMode = function(el) {\r
30527 var data = el.getData(),\r
30528 visMode = data[VISMODE];\r
30529 if (visMode === undefined) {\r
30530 data[VISMODE] = visMode = Element.VISIBILITY;\r
30531 }\r
30532 return visMode;\r
30533 },\r
30534 emptyRange = DOC.createRange ? DOC.createRange() : null,\r
30535 inputTags = {\r
30536 INPUT: true,\r
30537 TEXTAREA: true\r
30538 };\r
30539 if (Ext.isIE8) {\r
30540 var garbageBin = DOC.createElement('div'),\r
30541 destroyQueue = [],\r
30542 // prevent memory leaks in IE8\r
30543 // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment\r
30544 // This function is called to fully destroy an element on a timer so that code following the\r
30545 // remove call can still access the element.\r
30546 clearGarbage = Ext.Function.createBuffered(function() {\r
30547 var len = destroyQueue.length,\r
30548 i;\r
30549 for (i = 0; i < len; i++) {\r
30550 garbageBin.appendChild(destroyQueue[i]);\r
30551 }\r
30552 garbageBin.innerHTML = '';\r
30553 destroyQueue.length = 0;\r
30554 }, 10);\r
30555 }\r
30556 return {\r
30557 override: 'Ext.dom.Element',\r
30558 mixins: [\r
30559 'Ext.util.Animate'\r
30560 ],\r
30561 uses: [\r
30562 'Ext.dom.GarbageCollector',\r
30563 'Ext.dom.Fly',\r
30564 'Ext.event.publisher.MouseEnterLeave',\r
30565 'Ext.fx.Manager',\r
30566 'Ext.fx.Anim'\r
30567 ],\r
30568 skipGarbageCollection: false,\r
30569 _init: function(E) {\r
30570 Element = E;\r
30571 // now we can poke this into closure scope\r
30572 // We want to expose destroyQueue on the prototype for testing purposes\r
30573 if (WIN.__UNIT_TESTING__) {\r
30574 E.destroyQueue = destroyQueue;\r
30575 }\r
30576 // Allow overriding the attribute name and/or selector; this is\r
30577 // done only once for performance reasons\r
30578 E.tabbableSelector += ',[' + E.tabbableSavedCounterAttribute + ']';\r
30579 },\r
30580 statics: {\r
30581 selectableCls: Ext.baseCSSPrefix + 'selectable',\r
30582 unselectableCls: Ext.baseCSSPrefix + 'unselectable',\r
30583 // This selector will be modified at runtime in the _init() method above\r
30584 // to include the elements with saved tabindex in the returned set\r
30585 tabbableSelector: Ext.supports.CSS3NegationSelector ? 'a[href],button,iframe,input,select,textarea,[tabindex]:not([tabindex="-1"]),[contenteditable="true"]' : 'a[href],button,iframe,input,select,textarea,[tabindex],[contenteditable="true"]',\r
30586 // Anchor and link tags are special; they are only naturally focusable (and tabbable)\r
30587 // if they have href attribute, and tabbabledness is further platform/browser specific.\r
30588 // Thus we check it separately in the code.\r
30589 naturallyFocusableTags: {\r
30590 BUTTON: true,\r
30591 IFRAME: true,\r
30592 EMBED: true,\r
30593 INPUT: true,\r
30594 OBJECT: true,\r
30595 SELECT: true,\r
30596 TEXTAREA: true,\r
30597 HTML: Ext.isIE ? true : false\r
30598 },\r
30599 // <object> element is naturally tabbable only in IE8 and below\r
30600 naturallyTabbableTags: {\r
30601 BUTTON: true,\r
30602 IFRAME: true,\r
30603 INPUT: true,\r
30604 SELECT: true,\r
30605 TEXTAREA: true,\r
30606 OBJECT: Ext.isIE8m ? true : false\r
30607 },\r
30608 tabbableSavedCounterAttribute: 'data-tabindex-counter',\r
30609 tabbableSavedValueAttribute: 'data-tabindex-value',\r
30610 normalize: function(prop) {\r
30611 if (prop === 'float') {\r
30612 prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat';\r
30613 }\r
30614 // For '-ms-foo' we need msFoo\r
30615 return propertyCache[prop] || (propertyCache[prop] = prop.replace(msRe, 'ms-').replace(camelRe, camelReplaceFn));\r
30616 }\r
30617 },\r
30618 /**
30619 * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)
30620 * @param {String} className The class to add
30621 * @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
30622 * will be the Element instance. If this functions returns false, the class will not be added.
30623 * @param {Object} [scope] The scope to execute the testFn in.
30624 * @return {Ext.dom.Element} this
30625 */\r
30626 addClsOnClick: function(className, testFn, scope) {\r
30627 var me = this,\r
30628 dom = me.dom,\r
30629 hasTest = Ext.isFunction(testFn);\r
30630 me.on("mousedown", function() {\r
30631 if (hasTest && testFn.call(scope || me, me) === false) {\r
30632 return false;\r
30633 }\r
30634 Ext.fly(dom).addCls(className);\r
30635 var d = Ext.getDoc(),\r
30636 fn = function() {\r
30637 Ext.fly(dom).removeCls(className);\r
30638 d.removeListener("mouseup", fn);\r
30639 };\r
30640 d.on("mouseup", fn);\r
30641 });\r
30642 return me;\r
30643 },\r
30644 /**
30645 * Sets up event handlers to add and remove a css class when this element has the focus
30646 * @param {String} className The class to add
30647 * @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
30648 * will be the Element instance. If this functions returns false, the class will not be added.
30649 * @param {Object} [scope] The scope to execute the testFn in.
30650 * @return {Ext.dom.Element} this
30651 */\r
30652 addClsOnFocus: function(className, testFn, scope) {\r
30653 var me = this,\r
30654 dom = me.dom,\r
30655 hasTest = Ext.isFunction(testFn);\r
30656 me.on("focus", function() {\r
30657 if (hasTest && testFn.call(scope || me, me) === false) {\r
30658 return false;\r
30659 }\r
30660 Ext.fly(dom).addCls(className);\r
30661 });\r
30662 me.on("blur", function() {\r
30663 Ext.fly(dom).removeCls(className);\r
30664 });\r
30665 return me;\r
30666 },\r
30667 /**
30668 * Sets up event handlers to add and remove a css class when the mouse is over this element
30669 * @param {String} className The class to add
30670 * @param {Function} [testFn] A test function to execute before adding the class. The passed parameter
30671 * will be the Element instance. If this functions returns false, the class will not be added.
30672 * @param {Object} [scope] The scope to execute the testFn in.
30673 * @return {Ext.dom.Element} this
30674 */\r
30675 addClsOnOver: function(className, testFn, scope) {\r
30676 var me = this,\r
30677 dom = me.dom,\r
30678 hasTest = Ext.isFunction(testFn);\r
30679 me.hover(function() {\r
30680 if (hasTest && testFn.call(scope || me, me) === false) {\r
30681 return;\r
30682 }\r
30683 Ext.fly(dom).addCls(className);\r
30684 }, function() {\r
30685 Ext.fly(dom).removeCls(className);\r
30686 });\r
30687 return me;\r
30688 },\r
30689 /**
30690 * Convenience method for constructing a KeyMap
30691 * @param {String/Number/Number[]/Object} key Either a string with the keys to listen for, the numeric key code,
30692 * array of key codes or an object with the following options:
30693 * @param {Number/Array} key.key
30694 * @param {Boolean} key.shift
30695 * @param {Boolean} key.ctrl
30696 * @param {Boolean} key.alt
30697 * @param {Function} fn The function to call
30698 * @param {Object} [scope] The scope (`this` reference) in which the specified function is executed. Defaults to this Element.
30699 * @return {Ext.util.KeyMap} The KeyMap created
30700 */\r
30701 addKeyListener: function(key, fn, scope) {\r
30702 var config;\r
30703 if (typeof key !== 'object' || Ext.isArray(key)) {\r
30704 config = {\r
30705 target: this,\r
30706 key: key,\r
30707 fn: fn,\r
30708 scope: scope\r
30709 };\r
30710 } else {\r
30711 config = {\r
30712 target: this,\r
30713 key: key.key,\r
30714 shift: key.shift,\r
30715 ctrl: key.ctrl,\r
30716 alt: key.alt,\r
30717 fn: fn,\r
30718 scope: scope\r
30719 };\r
30720 }\r
30721 return new Ext.util.KeyMap(config);\r
30722 },\r
30723 /**
30724 * Creates a KeyMap for this element
30725 * @param {Object} config The KeyMap config. See {@link Ext.util.KeyMap} for more details
30726 * @return {Ext.util.KeyMap} The KeyMap created
30727 */\r
30728 addKeyMap: function(config) {\r
30729 return new Ext.util.KeyMap(Ext.apply({\r
30730 target: this\r
30731 }, config));\r
30732 },\r
30733 /**
30734 * @private
30735 */\r
30736 afterAnimate: function() {\r
30737 var shadow = this.shadow;\r
30738 if (shadow && !shadow.disabled && !shadow.animate) {\r
30739 shadow.show();\r
30740 }\r
30741 },\r
30742 /**
30743 * @private
30744 */\r
30745 anchorAnimX: function(anchor) {\r
30746 var xName = (anchor === 'l') ? 'right' : 'left';\r
30747 this.dom.style[xName] = '0px';\r
30748 },\r
30749 /**
30750 * @private
30751 * process the passed fx configuration.
30752 */\r
30753 anim: function(config) {\r
30754 if (!Ext.isObject(config)) {\r
30755 return (config) ? {} : false;\r
30756 }\r
30757 var me = this,\r
30758 duration = config.duration || Ext.fx.Anim.prototype.duration,\r
30759 easing = config.easing || 'ease',\r
30760 animConfig;\r
30761 if (config.stopAnimation) {\r
30762 me.stopAnimation();\r
30763 }\r
30764 Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id));\r
30765 // Clear any 'paused' defaults.\r
30766 Ext.fx.Manager.setFxDefaults(me.id, {\r
30767 delay: 0\r
30768 });\r
30769 animConfig = {\r
30770 // Pass the DOM reference. That's tested first so will be converted to an Ext.fx.Target fastest.\r
30771 target: me.dom,\r
30772 remove: config.remove,\r
30773 alternate: config.alternate || false,\r
30774 duration: duration,\r
30775 easing: easing,\r
30776 callback: config.callback,\r
30777 listeners: config.listeners,\r
30778 iterations: config.iterations || 1,\r
30779 scope: config.scope,\r
30780 block: config.block,\r
30781 concurrent: config.concurrent,\r
30782 delay: config.delay || 0,\r
30783 paused: true,\r
30784 keyframes: config.keyframes,\r
30785 from: config.from || {},\r
30786 to: Ext.apply({}, config),\r
30787 userConfig: config\r
30788 };\r
30789 Ext.apply(animConfig.to, config.to);\r
30790 // Anim API properties - backward compat\r
30791 delete animConfig.to.to;\r
30792 delete animConfig.to.from;\r
30793 delete animConfig.to.remove;\r
30794 delete animConfig.to.alternate;\r
30795 delete animConfig.to.keyframes;\r
30796 delete animConfig.to.iterations;\r
30797 delete animConfig.to.listeners;\r
30798 delete animConfig.to.target;\r
30799 delete animConfig.to.paused;\r
30800 delete animConfig.to.callback;\r
30801 delete animConfig.to.scope;\r
30802 delete animConfig.to.duration;\r
30803 delete animConfig.to.easing;\r
30804 delete animConfig.to.concurrent;\r
30805 delete animConfig.to.block;\r
30806 delete animConfig.to.stopAnimation;\r
30807 delete animConfig.to.delay;\r
30808 return animConfig;\r
30809 },\r
30810 /**
30811 * Calls `{@link #addAnimation}` and returns this Element (for call chaining). For
30812 * details, see `{@link #addAnimation}`.
30813 *
30814 * @param {Object} config Configuration for {@link Ext.fx.Anim}.
30815 * Note that the {@link Ext.fx.Anim#to to} config is required.
30816 * @return {Ext.dom.Element} this
30817 */\r
30818 animate: function(config) {\r
30819 this.addAnimation(config);\r
30820 return this;\r
30821 },\r
30822 /**
30823 * Starts a custom animation on this Element.
30824 *
30825 * The following properties may be specified in `from`, `to`, and `keyframe` objects:
30826 *
30827 * - `x` - The page X position in pixels.
30828 * - `y` - The page Y position in pixels
30829 * - `left` - The element's CSS `left` value. Units must be supplied.
30830 * - `top` - The element's CSS `top` value. Units must be supplied.
30831 * - `width` - The element's CSS `width` value. Units must be supplied.
30832 * - `height` - The element's CSS `height` value. Units must be supplied.
30833 * - `scrollLeft` - The element's `scrollLeft` value.
30834 * - `scrollTop` - The element's `scrollTop` value.
30835 * - `opacity` - The element's `opacity` value (between `0` and `1`).
30836 *
30837 * **Be aware** that animating an Element which is being used by an Ext Component
30838 * without in some way informing the Component about the changed element state will
30839 * result in incorrect Component behaviour. This is because the Component will be
30840 * using the old state of the element. To avoid this problem, it is now possible
30841 * to directly animate certain properties of Components.
30842 *
30843 * @param {Object} config Configuration for {@link Ext.fx.Anim}.
30844 * Note that the {@link Ext.fx.Anim#to to} config is required.
30845 * @return {Ext.fx.Anim} The new animation.
30846 */\r
30847 addAnimation: function(config) {\r
30848 var me = this,\r
30849 animId = me.dom.id || Ext.id(me.dom),\r
30850 listeners, anim, end;\r
30851 if (!Ext.fx.Manager.hasFxBlock(animId)) {\r
30852 // Bit of gymnastics here to ensure our internal listeners get bound first\r
30853 if (config.listeners) {\r
30854 listeners = config.listeners;\r
30855 delete config.listeners;\r
30856 }\r
30857 if (config.internalListeners) {\r
30858 config.listeners = config.internalListeners;\r
30859 delete config.internalListeners;\r
30860 }\r
30861 end = config.autoEnd;\r
30862 delete config.autoEnd;\r
30863 anim = new Ext.fx.Anim(me.anim(config));\r
30864 anim.on({\r
30865 afteranimate: 'afterAnimate',\r
30866 beforeanimate: 'beforeAnimate',\r
30867 scope: me,\r
30868 single: true\r
30869 });\r
30870 if (listeners) {\r
30871 anim.on(listeners);\r
30872 }\r
30873 Ext.fx.Manager.queueFx(anim);\r
30874 if (end) {\r
30875 anim.jumpToEnd();\r
30876 }\r
30877 }\r
30878 return anim;\r
30879 },\r
30880 /**
30881 * @private
30882 */\r
30883 beforeAnimate: function() {\r
30884 var shadow = this.shadow;\r
30885 if (shadow && !shadow.disabled && !shadow.animate) {\r
30886 shadow.hide();\r
30887 }\r
30888 },\r
30889 /**
30890 * Wraps the specified element with a special 9 element markup/CSS block that renders by default as
30891 * a gray container with a gradient background, rounded corners and a 4-way shadow.
30892 *
30893 * This special markup is used throughout Ext when box wrapping elements ({@link Ext.button.Button},
30894 * {@link Ext.panel.Panel} when {@link Ext.panel.Panel#frame frame=true}, {@link Ext.window.Window}).
30895 * The markup is of this form:
30896 *
30897 * <div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div>
30898 * <div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div>
30899 * <div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>
30900 *
30901 * Example usage:
30902 *
30903 * // Basic box wrap
30904 * Ext.get("foo").boxWrap();
30905 *
30906 * // You can also add a custom class and use CSS inheritance rules to customize the box look.
30907 * // 'x-box-blue' is a built-in alternative -- look at the related CSS definitions as an example
30908 * // for how to create a custom box wrap style.
30909 * Ext.get("foo").boxWrap().addCls("x-box-blue");
30910 *
30911 * @param {String} [class='x-box'] A base CSS class to apply to the containing wrapper element.
30912 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
30913 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
30914 * @return {Ext.dom.Element} The outermost wrapping element of the created box structure.
30915 */\r
30916 boxWrap: function(cls) {\r
30917 cls = cls || Ext.baseCSSPrefix + 'box';\r
30918 var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "' role='presentation'>" + Ext.String.format(boxMarkup, cls) + "</div>"));\r
30919 el.selectNode('.' + cls + '-mc').appendChild(this.dom);\r
30920 return el;\r
30921 },\r
30922 /**
30923 * Removes Empty, or whitespace filled text nodes. Combines adjacent text nodes.
30924 * @param {Boolean} [forceReclean=false] By default the element keeps track if it has been cleaned already
30925 * so you can call this over and over. However, if you update the element and need to force a re-clean, you
30926 * can pass true.
30927 */\r
30928 clean: function(forceReclean) {\r
30929 var me = this,\r
30930 dom = me.dom,\r
30931 data = me.getData(),\r
30932 n = dom.firstChild,\r
30933 ni = -1,\r
30934 nx;\r
30935 if (data.isCleaned && forceReclean !== true) {\r
30936 return me;\r
30937 }\r
30938 while (n) {\r
30939 nx = n.nextSibling;\r
30940 if (n.nodeType === 3) {\r
30941 // Remove empty/whitespace text nodes\r
30942 if (!(nonSpaceRe.test(n.nodeValue))) {\r
30943 dom.removeChild(n);\r
30944 }\r
30945 // Combine adjacent text nodes\r
30946 else if (nx && nx.nodeType === 3) {\r
30947 n.appendData(Ext.String.trim(nx.data));\r
30948 dom.removeChild(nx);\r
30949 nx = n.nextSibling;\r
30950 n.nodeIndex = ++ni;\r
30951 }\r
30952 } else {\r
30953 // Recursively clean\r
30954 Ext.fly(n, '_clean').clean();\r
30955 n.nodeIndex = ++ni;\r
30956 }\r
30957 n = nx;\r
30958 }\r
30959 data.isCleaned = true;\r
30960 return me;\r
30961 },\r
30962 /**
30963 * Empties this element. Removes all child nodes.
30964 */\r
30965 empty: emptyRange ? function() {\r
30966 var dom = this.dom;\r
30967 if (dom.firstChild) {\r
30968 emptyRange.setStartBefore(dom.firstChild);\r
30969 emptyRange.setEndAfter(dom.lastChild);\r
30970 emptyRange.deleteContents();\r
30971 }\r
30972 } : function() {\r
30973 var dom = this.dom;\r
30974 while (dom.lastChild) {\r
30975 dom.removeChild(dom.lastChild);\r
30976 }\r
30977 },\r
30978 clearListeners: function() {\r
30979 this.removeAnchor();\r
30980 this.callParent();\r
30981 },\r
30982 /**
30983 * Clears positioning back to the default when the document was loaded.
30984 * @param {String} [value=''] The value to use for the left, right, top, bottom.
30985 * You could use 'auto'.
30986 * @return {Ext.dom.Element} this
30987 */\r
30988 clearPositioning: function(value) {\r
30989 value = value || '';\r
30990 return this.setStyle({\r
30991 left: value,\r
30992 right: value,\r
30993 top: value,\r
30994 bottom: value,\r
30995 'z-index': '',\r
30996 position: 'static'\r
30997 });\r
30998 },\r
30999 /**
31000 * Creates a proxy element of this element
31001 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
31002 * @param {String/HTMLElement} [renderTo] The element or element id to render the proxy to. Defaults to: document.body.
31003 * @param {Boolean} [matchBox=false] True to align and size the proxy to this element now.
31004 * @return {Ext.dom.Element} The new proxy element
31005 */\r
31006 createProxy: function(config, renderTo, matchBox) {\r
31007 config = (typeof config === 'object') ? config : {\r
31008 tag: "div",\r
31009 role: 'presentation',\r
31010 cls: config\r
31011 };\r
31012 var me = this,\r
31013 proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) : Ext.DomHelper.insertBefore(me.dom, config, true);\r
31014 proxy.setVisibilityMode(Element.DISPLAY);\r
31015 proxy.hide();\r
31016 if (matchBox && me.setBox && me.getBox) {\r
31017 // check to make sure Element_position.js is loaded\r
31018 proxy.setBox(me.getBox());\r
31019 }\r
31020 return proxy;\r
31021 },\r
31022 /**
31023 * Clears any opacity settings from this element. Required in some cases for IE.
31024 * @return {Ext.dom.Element} this
31025 */\r
31026 clearOpacity: function() {\r
31027 return this.setOpacity('');\r
31028 },\r
31029 /**
31030 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
31031 * @return {Ext.dom.Element} this
31032 */\r
31033 clip: function() {\r
31034 var me = this,\r
31035 data = me.getData(),\r
31036 style;\r
31037 if (!data[ISCLIPPED]) {\r
31038 data[ISCLIPPED] = true;\r
31039 style = me.getStyle([\r
31040 OVERFLOW,\r
31041 OVERFLOWX,\r
31042 OVERFLOWY\r
31043 ]);\r
31044 data[ORIGINALCLIP] = {\r
31045 o: style[OVERFLOW],\r
31046 x: style[OVERFLOWX],\r
31047 y: style[OVERFLOWY]\r
31048 };\r
31049 me.setStyle(OVERFLOW, HIDDEN);\r
31050 me.setStyle(OVERFLOWX, HIDDEN);\r
31051 me.setStyle(OVERFLOWY, HIDDEN);\r
31052 }\r
31053 return me;\r
31054 },\r
31055 destroy: function() {\r
31056 var me = this,\r
31057 dom = me.dom,\r
31058 data = me.getData(),\r
31059 maskEl, maskMsg;\r
31060 if (dom && me.isAnimate) {\r
31061 me.stopAnimation();\r
31062 }\r
31063 me.callParent();\r
31064 // prevent memory leaks in IE8\r
31065 // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment\r
31066 // must not be document, documentElement, body or window object\r
31067 // Have to use != instead of !== for IE8 or it will not recognize that the window\r
31068 // objects are equal\r
31069 if (dom && Ext.isIE8 && (dom.window != dom) && (dom.nodeType !== 9) && (dom.tagName !== 'BODY') && (dom.tagName !== 'HTML')) {\r
31070 destroyQueue[destroyQueue.length] = dom;\r
31071 // Will perform extra IE8 cleanup in 10 milliseconds\r
31072 // see http://social.msdn.microsoft.com/Forums/ie/en-US/c76967f0-dcf8-47d0-8984-8fe1282a94f5/ie-appendchildremovechild-memory-problem?forum=iewebdevelopment\r
31073 clearGarbage();\r
31074 }\r
31075 if (data) {\r
31076 maskEl = data.maskEl;\r
31077 maskMsg = data.maskMsg;\r
31078 if (maskEl) {\r
31079 maskEl.destroy();\r
31080 }\r
31081 if (maskMsg) {\r
31082 maskMsg.destroy();\r
31083 }\r
31084 }\r
31085 },\r
31086 /**
31087 * Convenience method for setVisibilityMode(Element.DISPLAY).
31088 * @param {String} [display] What to set display to when visible
31089 * @return {Ext.dom.Element} this
31090 */\r
31091 enableDisplayMode: function(display) {\r
31092 var me = this;\r
31093 me.setVisibilityMode(Element.DISPLAY);\r
31094 if (display !== undefined) {\r
31095 me.getData()[ORIGINALDISPLAY] = display;\r
31096 }\r
31097 return me;\r
31098 },\r
31099 /**
31100 * Fade an element in (from transparent to opaque). The ending opacity can be specified using the `opacity`
31101 * config option. Usage:
31102 *
31103 * // default: fade in from opacity 0 to 100%
31104 * el.fadeIn();
31105 *
31106 * // custom: fade in from opacity 0 to 75% over 2 seconds
31107 * el.fadeIn({ opacity: .75, duration: 2000});
31108 *
31109 * // common config options shown with default values
31110 * el.fadeIn({
31111 * opacity: 1, //can be any value between 0 and 1 (e.g. .5)
31112 * easing: 'easeOut',
31113 * duration: 500
31114 * });
31115 *
31116 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
31117 * @return {Ext.dom.Element} The Element
31118 */\r
31119 fadeIn: function(o) {\r
31120 var me = this,\r
31121 dom = me.dom;\r
31122 me.animate(Ext.apply({}, o, {\r
31123 opacity: 1,\r
31124 internalListeners: {\r
31125 beforeanimate: function(anim) {\r
31126 // restore any visibility/display that may have \r
31127 // been applied by a fadeout animation\r
31128 var el = Ext.fly(dom, '_anim');\r
31129 if (el.isStyle('display', 'none')) {\r
31130 el.setDisplayed('');\r
31131 } else {\r
31132 el.show();\r
31133 }\r
31134 }\r
31135 }\r
31136 }));\r
31137 return this;\r
31138 },\r
31139 /**
31140 * Fade an element out (from opaque to transparent). The ending opacity can be specified using the `opacity`
31141 * config option. Note that IE may require `useDisplay:true` in order to redisplay correctly.
31142 * Usage:
31143 *
31144 * // default: fade out from the element's current opacity to 0
31145 * el.fadeOut();
31146 *
31147 * // custom: fade out from the element's current opacity to 25% over 2 seconds
31148 * el.fadeOut({ opacity: .25, duration: 2000});
31149 *
31150 * // common config options shown with default values
31151 * el.fadeOut({
31152 * opacity: 0, //can be any value between 0 and 1 (e.g. .5)
31153 * easing: 'easeOut',
31154 * duration: 500,
31155 * remove: false,
31156 * useDisplay: false
31157 * });
31158 *
31159 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
31160 * @return {Ext.dom.Element} The Element
31161 */\r
31162 fadeOut: function(o) {\r
31163 var me = this,\r
31164 dom = me.dom;\r
31165 o = Ext.apply({\r
31166 opacity: 0,\r
31167 internalListeners: {\r
31168 afteranimate: function(anim) {\r
31169 if (dom && anim.to.opacity === 0) {\r
31170 var el = Ext.fly(dom, '_anim');\r
31171 if (o.useDisplay) {\r
31172 el.setDisplayed(false);\r
31173 } else {\r
31174 el.hide();\r
31175 }\r
31176 }\r
31177 }\r
31178 }\r
31179 }, o);\r
31180 me.animate(o);\r
31181 return me;\r
31182 },\r
31183 /**
31184 * @private
31185 */\r
31186 fixDisplay: function() {\r
31187 var me = this;\r
31188 if (me.isStyle(DISPLAY, NONE)) {\r
31189 me.setStyle(VISIBILITY, HIDDEN);\r
31190 me.setStyle(DISPLAY, me._getDisplay());\r
31191 // first try reverting to default\r
31192 if (me.isStyle(DISPLAY, NONE)) {\r
31193 // if that fails, default to block\r
31194 me.setStyle(DISPLAY, "block");\r
31195 }\r
31196 }\r
31197 },\r
31198 /**
31199 * Shows a ripple of exploding, attenuating borders to draw attention to an Element. Usage:
31200 *
31201 * // default: a single light blue ripple
31202 * el.frame();
31203 *
31204 * // custom: 3 red ripples lasting 3 seconds total
31205 * el.frame("#ff0000", 3, { duration: 3000 });
31206 *
31207 * // common config options shown with default values
31208 * el.frame("#C3DAF9", 1, {
31209 * duration: 1000 // duration of each individual ripple.
31210 * // Note: Easing is not configurable and will be ignored if included
31211 * });
31212 *
31213 * @param {String} [color='#C3DAF9'] The hex color value for the border.
31214 * @param {Number} [count=1] The number of ripples to display.
31215 * @param {Object} [options] Object literal with any of the {@link Ext.fx.Anim} config options
31216 * @return {Ext.dom.Element} The Element
31217 */\r
31218 frame: function(color, count, obj) {\r
31219 var me = this,\r
31220 dom = me.dom,\r
31221 beforeAnim;\r
31222 color = color || '#C3DAF9';\r
31223 count = count || 1;\r
31224 obj = obj || {};\r
31225 beforeAnim = function() {\r
31226 var el = Ext.fly(dom, '_anim'),\r
31227 animScope = this,\r
31228 box, proxy, proxyAnim;\r
31229 el.show();\r
31230 box = el.getBox();\r
31231 proxy = Ext.getBody().createChild({\r
31232 role: 'presentation',\r
31233 id: el.dom.id + '-anim-proxy',\r
31234 style: {\r
31235 position: 'absolute',\r
31236 'pointer-events': 'none',\r
31237 'z-index': 35000,\r
31238 border: '0px solid ' + color\r
31239 }\r
31240 });\r
31241 proxyAnim = new Ext.fx.Anim({\r
31242 target: proxy,\r
31243 duration: obj.duration || 1000,\r
31244 iterations: count,\r
31245 from: {\r
31246 top: box.y,\r
31247 left: box.x,\r
31248 borderWidth: 0,\r
31249 opacity: 1,\r
31250 height: box.height,\r
31251 width: box.width\r
31252 },\r
31253 to: {\r
31254 top: box.y - 20,\r
31255 left: box.x - 20,\r
31256 borderWidth: 10,\r
31257 opacity: 0,\r
31258 height: box.height + 40,\r
31259 width: box.width + 40\r
31260 }\r
31261 });\r
31262 proxyAnim.on('afteranimate', function() {\r
31263 proxy.destroy();\r
31264 // kill the no-op element animation created below\r
31265 animScope.end();\r
31266 });\r
31267 };\r
31268 me.animate({\r
31269 // See "A Note About Wrapped Animations" at the top of this class:\r
31270 duration: (Math.max(obj.duration, 500) * 2) || 2000,\r
31271 listeners: {\r
31272 beforeanimate: {\r
31273 fn: beforeAnim\r
31274 }\r
31275 },\r
31276 callback: obj.callback,\r
31277 scope: obj.scope\r
31278 });\r
31279 return me;\r
31280 },\r
31281 /**
31282 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like `#fff`)
31283 * and valid values are convert to standard 6 digit hex color.
31284 * @param {String} attr The css attribute
31285 * @param {String} defaultValue The default value to use when a valid color isn't found
31286 * @param {String} [prefix] defaults to #. Use an empty string when working with
31287 * color anims.
31288 * @private
31289 */\r
31290 getColor: function(attr, defaultValue, prefix) {\r
31291 var v = this.getStyle(attr),\r
31292 color = prefix || prefix === '' ? prefix : '#',\r
31293 h, len,\r
31294 i = 0;\r
31295 if (!v || (/transparent|inherit/.test(v))) {\r
31296 return defaultValue;\r
31297 }\r
31298 if (/^r/.test(v)) {\r
31299 v = v.slice(4, v.length - 1).split(',');\r
31300 len = v.length;\r
31301 for (; i < len; i++) {\r
31302 h = parseInt(v[i], 10);\r
31303 color += (h < 16 ? '0' : '') + h.toString(16);\r
31304 }\r
31305 } else {\r
31306 v = v.replace('#', '');\r
31307 color += v.length === 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;\r
31308 }\r
31309 return (color.length > 5 ? color.toLowerCase() : defaultValue);\r
31310 },\r
31311 /**
31312 * Gets this element's {@link Ext.ElementLoader ElementLoader}
31313 * @return {Ext.ElementLoader} The loader
31314 */\r
31315 getLoader: function() {\r
31316 var me = this,\r
31317 data = me.getData(),\r
31318 loader = data.loader;\r
31319 if (!loader) {\r
31320 data.loader = loader = new Ext.ElementLoader({\r
31321 target: me\r
31322 });\r
31323 }\r
31324 return loader;\r
31325 },\r
31326 /**
31327 * Gets an object with all CSS positioning properties. Useful along with
31328 * #setPostioning to get snapshot before performing an update and then restoring
31329 * the element.
31330 * @param {Boolean} [autoPx=false] true to return pixel values for "auto" styles.
31331 * @return {Object}
31332 */\r
31333 getPositioning: function(autoPx) {\r
31334 var styles = this.getStyle([\r
31335 'left',\r
31336 'top',\r
31337 'position',\r
31338 'z-index'\r
31339 ]),\r
31340 dom = this.dom;\r
31341 if (autoPx) {\r
31342 if (styles.left === 'auto') {\r
31343 styles.left = dom.offsetLeft + 'px';\r
31344 }\r
31345 if (styles.top === 'auto') {\r
31346 styles.top = dom.offsetTop + 'px';\r
31347 }\r
31348 }\r
31349 return styles;\r
31350 },\r
31351 /**
31352 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the ending point
31353 * of the effect. Usage:
31354 *
31355 * // default: slide the element downward while fading out
31356 * el.ghost();
31357 *
31358 * // custom: slide the element out to the right with a 2-second duration
31359 * el.ghost('r', { duration: 2000 });
31360 *
31361 * // common config options shown with default values
31362 * el.ghost('b', {
31363 * easing: 'easeOut',
31364 * duration: 500
31365 * });
31366 *
31367 * @param {String} anchor (optional) One of the valid {@link Ext.fx.Anim} anchor positions (defaults to bottom: 'b')
31368 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
31369 * @return {Ext.dom.Element} The Element
31370 */\r
31371 ghost: function(anchor, obj) {\r
31372 var me = this,\r
31373 dom = me.dom,\r
31374 beforeAnim;\r
31375 anchor = anchor || "b";\r
31376 beforeAnim = function() {\r
31377 var el = Ext.fly(dom, '_anim'),\r
31378 width = el.getWidth(),\r
31379 height = el.getHeight(),\r
31380 xy = el.getXY(),\r
31381 position = el.getPositioning(),\r
31382 to = {\r
31383 opacity: 0\r
31384 };\r
31385 switch (anchor) {\r
31386 case 't':\r
31387 to.y = xy[1] - height;\r
31388 break;\r
31389 case 'l':\r
31390 to.x = xy[0] - width;\r
31391 break;\r
31392 case 'r':\r
31393 to.x = xy[0] + width;\r
31394 break;\r
31395 case 'b':\r
31396 to.y = xy[1] + height;\r
31397 break;\r
31398 case 'tl':\r
31399 to.x = xy[0] - width;\r
31400 to.y = xy[1] - height;\r
31401 break;\r
31402 case 'bl':\r
31403 to.x = xy[0] - width;\r
31404 to.y = xy[1] + height;\r
31405 break;\r
31406 case 'br':\r
31407 to.x = xy[0] + width;\r
31408 to.y = xy[1] + height;\r
31409 break;\r
31410 case 'tr':\r
31411 to.x = xy[0] + width;\r
31412 to.y = xy[1] - height;\r
31413 break;\r
31414 }\r
31415 this.to = to;\r
31416 this.on('afteranimate', function() {\r
31417 var el = Ext.fly(dom, '_anim');\r
31418 if (el) {\r
31419 el.hide();\r
31420 el.clearOpacity();\r
31421 el.setPositioning(position);\r
31422 }\r
31423 });\r
31424 };\r
31425 me.animate(Ext.applyIf(obj || {}, {\r
31426 duration: 500,\r
31427 easing: 'ease-out',\r
31428 listeners: {\r
31429 beforeanimate: beforeAnim\r
31430 }\r
31431 }));\r
31432 return me;\r
31433 },\r
31434 /**
31435 * @override
31436 * Hide this element - Uses display mode to determine whether to use "display",
31437 * "visibility", "offsets", or "clip". See {@link #setVisible}.
31438 * @param {Boolean/Object} [animate] true for the default animation or a standard
31439 * Element animation config object
31440 * @return {Ext.dom.Element} this
31441 */\r
31442 hide: function(animate) {\r
31443 // hideMode override\r
31444 if (typeof animate === 'string') {\r
31445 this.setVisible(false, animate);\r
31446 return this;\r
31447 }\r
31448 this.setVisible(false, this.anim(animate));\r
31449 return this;\r
31450 },\r
31451 /**
31452 * Highlights the Element by setting a color (applies to the background-color by default, but can be changed using
31453 * the "attr" config option) and then fading back to the original color. If no original color is available, you
31454 * should provide the "endColor" config option which will be cleared after the animation. Usage:
31455 *
31456 * // default: highlight background to yellow
31457 * el.highlight();
31458 *
31459 * // custom: highlight foreground text to blue for 2 seconds
31460 * el.highlight("0000ff", { attr: 'color', duration: 2000 });
31461 *
31462 * // common config options shown with default values
31463 * el.highlight("ffff9c", {
31464 * attr: "backgroundColor", //can be any valid CSS property (attribute) that supports a color value
31465 * endColor: (current color) or "ffffff",
31466 * easing: 'easeIn',
31467 * duration: 1000
31468 * });
31469 *
31470 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading #
31471 * (defaults to yellow: 'ffff9c')
31472 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
31473 * @return {Ext.dom.Element} The Element
31474 */\r
31475 highlight: function(color, o) {\r
31476 var me = this,\r
31477 dom = me.dom,\r
31478 from = {},\r
31479 restore, to, attr, lns, event, fn;\r
31480 o = o || {};\r
31481 lns = o.listeners || {};\r
31482 attr = o.attr || 'backgroundColor';\r
31483 from[attr] = color || 'ffff9c';\r
31484 if (!o.to) {\r
31485 to = {};\r
31486 to[attr] = o.endColor || me.getColor(attr, 'ffffff', '');\r
31487 } else {\r
31488 to = o.to;\r
31489 }\r
31490 // Don't apply directly on lns, since we reference it in our own callbacks below\r
31491 o.listeners = Ext.apply(Ext.apply({}, lns), {\r
31492 beforeanimate: function() {\r
31493 restore = dom.style[attr];\r
31494 var el = Ext.fly(dom, '_anim');\r
31495 el.clearOpacity();\r
31496 el.show();\r
31497 event = lns.beforeanimate;\r
31498 if (event) {\r
31499 fn = event.fn || event;\r
31500 return fn.apply(event.scope || lns.scope || WIN, arguments);\r
31501 }\r
31502 },\r
31503 afteranimate: function() {\r
31504 if (dom) {\r
31505 dom.style[attr] = restore;\r
31506 }\r
31507 event = lns.afteranimate;\r
31508 if (event) {\r
31509 fn = event.fn || event;\r
31510 fn.apply(event.scope || lns.scope || WIN, arguments);\r
31511 }\r
31512 }\r
31513 });\r
31514 me.animate(Ext.apply({}, o, {\r
31515 duration: 1000,\r
31516 easing: 'ease-in',\r
31517 from: from,\r
31518 to: to\r
31519 }));\r
31520 return me;\r
31521 },\r
31522 /**
31523 * Sets up event handlers to call the passed functions when the mouse is moved into and out of the Element.
31524 * @param {Function} overFn The function to call when the mouse enters the Element.
31525 * @param {Function} outFn The function to call when the mouse leaves the Element.
31526 * @param {Object} [scope] The scope (`this` reference) in which the functions are executed. Defaults
31527 * to the Element's DOM element.
31528 * @param {Object} [options] Options for the listener. See {@link Ext.util.Observable#addListener the
31529 * options parameter}.
31530 * @return {Ext.dom.Element} this
31531 */\r
31532 hover: function(overFn, outFn, scope, options) {\r
31533 var me = this;\r
31534 me.on('mouseenter', overFn, scope || me.dom, options);\r
31535 me.on('mouseleave', outFn, scope || me.dom, options);\r
31536 return me;\r
31537 },\r
31538 /**
31539 * Initializes a {@link Ext.dd.DD} drag drop object for this element.
31540 * @param {String} group The group the DD object is member of
31541 * @param {Object} config The DD config object
31542 * @param {Object} overrides An object containing methods to override/implement on the DD object
31543 * @return {Ext.dd.DD} The DD object
31544 */\r
31545 initDD: function(group, config, overrides) {\r
31546 var dd = new Ext.dd.DD(Ext.id(this.dom), group, config);\r
31547 return Ext.apply(dd, overrides);\r
31548 },\r
31549 /**
31550 * Initializes a {@link Ext.dd.DDProxy} object for this element.
31551 * @param {String} group The group the DDProxy object is member of
31552 * @param {Object} config The DDProxy config object
31553 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
31554 * @return {Ext.dd.DDProxy} The DDProxy object
31555 */\r
31556 initDDProxy: function(group, config, overrides) {\r
31557 var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config);\r
31558 return Ext.apply(dd, overrides);\r
31559 },\r
31560 /**
31561 * Initializes a {@link Ext.dd.DDTarget} object for this element.
31562 * @param {String} group The group the DDTarget object is member of
31563 * @param {Object} config The DDTarget config object
31564 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
31565 * @return {Ext.dd.DDTarget} The DDTarget object
31566 */\r
31567 initDDTarget: function(group, config, overrides) {\r
31568 var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config);\r
31569 return Ext.apply(dd, overrides);\r
31570 },\r
31571 /**
31572 * Checks whether this element can be focused programmatically or by clicking.
31573 * To check if an element is in the document tab flow, use {@link #isTabbable}.
31574 *
31575 * @return {Boolean} True if the element is focusable
31576 */\r
31577 isFocusable: function() {\r
31578 var dom = this.dom,\r
31579 focusable = false,\r
31580 nodeName;\r
31581 if (dom && !dom.disabled) {\r
31582 nodeName = dom.nodeName;\r
31583 /*
31584 * An element is focusable if:
31585 * - It is naturally focusable, or
31586 * - It is an anchor or link with href attribute, or
31587 * - It has a tabIndex, or
31588 * - It is an editing host (contenteditable="true")
31589 *
31590 * Also note that we can't check dom.tabIndex because IE will return 0
31591 * for elements that have no tabIndex attribute defined, regardless of
31592 * whether they are naturally focusable or not.
31593 */\r
31594 focusable = !!Ext.Element.naturallyFocusableTags[nodeName] || ((nodeName === 'A' || nodeName === 'LINK') && !!dom.href) || dom.getAttribute('tabIndex') != null || dom.contentEditable === 'true';\r
31595 // In IE8, <input type="hidden"> does not have a corresponding style\r
31596 // so isVisible() will assume that it's not hidden.\r
31597 if (Ext.isIE8 && nodeName === 'INPUT' && dom.type === 'hidden') {\r
31598 focusable = false;\r
31599 }\r
31600 // Invisible elements cannot be focused, so check that as well\r
31601 focusable = focusable && this.isVisible(true);\r
31602 }\r
31603 return focusable;\r
31604 },\r
31605 /**
31606 * Returns `true` if this Element is an input field, or is editable in any way.
31607 * @return {Boolean} `true` if this Element is an input field, or is editable in any way.
31608 */\r
31609 isInputField: function() {\r
31610 var dom = this.dom,\r
31611 contentEditable = dom.contentEditable;\r
31612 // contentEditable will default to inherit if not specified, only check if the\r
31613 // attribute has been set or explicitly set to true\r
31614 // http://html5doctor.com/the-contenteditable-attribute/\r
31615 // Also skip <input> tags of type="button", we use them for checkboxes\r
31616 // and radio buttons\r
31617 if ((inputTags[dom.tagName] && dom.type !== 'button') || (contentEditable === '' || contentEditable === 'true')) {\r
31618 return true;\r
31619 }\r
31620 return false;\r
31621 },\r
31622 /**
31623 * Checks whether this element participates in the sequential focus navigation,
31624 * and can be reached by using Tab key.
31625 *
31626 * @param {Boolean} [includeHidden=false] pass `true` if hidden, or unattached elements should be returned.
31627 * @return {Boolean} True if the element is tabbable.
31628 */\r
31629 isTabbable: function(includeHidden) {\r
31630 var dom = this.dom,\r
31631 tabbable = false,\r
31632 nodeName, hasIndex, tabIndex;\r
31633 if (dom && !dom.disabled) {\r
31634 nodeName = dom.nodeName;\r
31635 // Can't use dom.tabIndex here because IE will return 0 for elements\r
31636 // that have no tabindex attribute defined, regardless of whether they are\r
31637 // naturally tabbable or not.\r
31638 tabIndex = dom.getAttribute('tabIndex');\r
31639 hasIndex = tabIndex != null;\r
31640 tabIndex -= 0;\r
31641 // Anchors and links are only naturally tabbable if they have href attribute\r
31642 // See http://www.w3.org/TR/html5/editing.html#specially-focusable\r
31643 if (nodeName === 'A' || nodeName === 'LINK') {\r
31644 if (dom.href) {\r
31645 // It is also possible to make an anchor untabbable by setting\r
31646 // tabIndex < 0 on it\r
31647 tabbable = hasIndex && tabIndex < 0 ? false : true;\r
31648 } else // Anchor w/o href is tabbable if it has tabIndex >= 0,\r
31649 // or if it's editable \r
31650 {\r
31651 if (dom.contentEditable === 'true') {\r
31652 tabbable = !hasIndex || (hasIndex && tabIndex >= 0) ? true : false;\r
31653 } else {\r
31654 tabbable = hasIndex && tabIndex >= 0 ? true : false;\r
31655 }\r
31656 }\r
31657 }\r
31658 // If an element has contenteditable="true" or is naturally tabbable,\r
31659 // then it is a potential candidate unless its tabIndex is < 0.\r
31660 else if (dom.contentEditable === 'true' || Ext.Element.naturallyTabbableTags[nodeName]) {\r
31661 tabbable = hasIndex && tabIndex < 0 ? false : true;\r
31662 } else // That leaves non-editable elements that can only be made tabbable\r
31663 // by slapping tabIndex >= 0 on them\r
31664 {\r
31665 if (hasIndex && tabIndex >= 0) {\r
31666 tabbable = true;\r
31667 }\r
31668 }\r
31669 // In IE8, <input type="hidden"> does not have a corresponding style\r
31670 // so isVisible() will assume that it's not hidden.\r
31671 if (Ext.isIE8 && nodeName === 'INPUT' && dom.type === 'hidden') {\r
31672 tabbable = false;\r
31673 }\r
31674 // Invisible elements can't be tabbed into. If we have a component ref\r
31675 // we'll also check if the component itself is visible before incurring\r
31676 // the expense of DOM style reads.\r
31677 // Allow caller to specify that hiddens should be included.\r
31678 tabbable = tabbable && (includeHidden || ((!this.component || this.component.isVisible(true)) && this.isVisible(true)));\r
31679 }\r
31680 return tabbable;\r
31681 },\r
31682 /**
31683 * Returns true if this element is masked. Also re-centers any displayed message
31684 * within the mask.
31685 *
31686 * @param {Boolean} [deep] Go up the DOM hierarchy to determine if any parent
31687 * element is masked.
31688 *
31689 * @return {Boolean}
31690 */\r
31691 isMasked: function(deep) {\r
31692 var me = this,\r
31693 data = me.getData(),\r
31694 maskEl = data.maskEl,\r
31695 maskMsg = data.maskMsg,\r
31696 hasMask = false,\r
31697 parent;\r
31698 if (maskEl && maskEl.isVisible()) {\r
31699 if (maskMsg) {\r
31700 maskMsg.center(me);\r
31701 }\r
31702 hasMask = true;\r
31703 } else if (deep) {\r
31704 parent = me.findParentNode();\r
31705 if (parent) {\r
31706 return Ext.fly(parent).isMasked(deep);\r
31707 }\r
31708 }\r
31709 return hasMask;\r
31710 },\r
31711 /**
31712 * Direct access to the Ext.ElementLoader {@link Ext.ElementLoader#method-load} method.
31713 * The method takes the same object parameter as {@link Ext.ElementLoader#method-load}
31714 * @param {Object} options a options object for Ext.ElementLoader {@link Ext.ElementLoader#method-load}
31715 * @return {Ext.dom.Element} this
31716 */\r
31717 load: function(options) {\r
31718 this.getLoader().load(options);\r
31719 return this;\r
31720 },\r
31721 /**
31722 * Puts a mask over this element to disable user interaction.
31723 * This method can only be applied to elements which accept child nodes. Use
31724 * {@link #unmask} to remove the mask.
31725 *
31726 * @param {String} [msg] A message to display in the mask
31727 * @param {String} [msgCls] A css class to apply to the msg element
31728 * @return {Ext.dom.Element} The mask element
31729 */\r
31730 mask: function(msg, msgCls, /* private - passed by AbstractComponent.mask to avoid the need to interrogate the DOM to get the height*/\r
31731 elHeight) {\r
31732 var me = this,\r
31733 dom = me.dom,\r
31734 data = me.getData(),\r
31735 maskEl = data.maskEl,\r
31736 maskMsg;\r
31737 if (!(bodyRe.test(dom.tagName) && me.getStyle('position') === 'static')) {\r
31738 me.addCls(XMASKEDRELATIVE);\r
31739 }\r
31740 // We always needs to recreate the mask since the DOM element may have been re-created\r
31741 if (maskEl) {\r
31742 maskEl.destroy();\r
31743 }\r
31744 maskEl = Ext.DomHelper.append(dom, {\r
31745 role: 'presentation',\r
31746 cls: Ext.baseCSSPrefix + "mask " + Ext.baseCSSPrefix + "border-box",\r
31747 children: {\r
31748 role: 'presentation',\r
31749 cls: msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG,\r
31750 cn: {\r
31751 tag: 'div',\r
31752 role: 'presentation',\r
31753 cls: Ext.baseCSSPrefix + 'mask-msg-inner',\r
31754 cn: {\r
31755 tag: 'div',\r
31756 role: 'presentation',\r
31757 cls: Ext.baseCSSPrefix + 'mask-msg-text',\r
31758 html: msg || ''\r
31759 }\r
31760 }\r
31761 }\r
31762 }, true);\r
31763 maskMsg = Ext.get(maskEl.dom.firstChild);\r
31764 data.maskEl = maskEl;\r
31765 me.addCls(XMASKED);\r
31766 maskEl.setDisplayed(true);\r
31767 if (typeof msg === 'string') {\r
31768 maskMsg.setDisplayed(true);\r
31769 maskMsg.center(me);\r
31770 } else {\r
31771 maskMsg.setDisplayed(false);\r
31772 }\r
31773 if (dom === DOC.body) {\r
31774 maskEl.addCls(Ext.baseCSSPrefix + 'mask-fixed');\r
31775 }\r
31776 // When masking the body, don't touch its tabbable state\r
31777 me.saveTabbableState({\r
31778 skipSelf: dom === DOC.body\r
31779 });\r
31780 // ie will not expand full height automatically\r
31781 if (Ext.isIE9m && dom !== DOC.body && me.isStyle('height', 'auto')) {\r
31782 maskEl.setSize(undefined, elHeight || me.getHeight());\r
31783 }\r
31784 return maskEl;\r
31785 },\r
31786 /**
31787 * Monitors this Element for the mouse leaving. Calls the function after the specified delay only if
31788 * the mouse was not moved back into the Element within the delay. If the mouse *was* moved
31789 * back in, the function is not called.
31790 * @param {Number} delay The delay **in milliseconds** to wait for possible mouse re-entry before calling the handler function.
31791 * @param {Function} handler The function to call if the mouse remains outside of this Element for the specified time.
31792 * @param {Object} [scope] The scope (`this` reference) in which the handler function executes. Defaults to this Element.
31793 * @return {Object} The listeners object which was added to this element so that monitoring can be stopped. Example usage:
31794 *
31795 * // Hide the menu if the mouse moves out for 250ms or more
31796 * this.mouseLeaveMonitor = this.menuEl.monitorMouseLeave(250, this.hideMenu, this);
31797 *
31798 * ...
31799 * // Remove mouseleave monitor on menu destroy
31800 * this.menuEl.un(this.mouseLeaveMonitor);
31801 *
31802 */\r
31803 monitorMouseLeave: function(delay, handler, scope) {\r
31804 var me = this,\r
31805 timer,\r
31806 listeners = {\r
31807 mouseleave: function(e) {\r
31808 if (Ext.isIE9m) {\r
31809 e.enableIEAsync();\r
31810 }\r
31811 timer = Ext.defer(handler, delay, scope || me, [\r
31812 e\r
31813 ]);\r
31814 },\r
31815 mouseenter: function() {\r
31816 clearTimeout(timer);\r
31817 }\r
31818 };\r
31819 me.on(listeners);\r
31820 return listeners;\r
31821 },\r
31822 /**
31823 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the element will
31824 * be hidden (visibility = 'hidden') but block elements will still take up space in the document. Usage:
31825 *
31826 * // default
31827 * el.puff();
31828 *
31829 * // common config options shown with default values
31830 * el.puff({
31831 * easing: 'easeOut',
31832 * duration: 500,
31833 * useDisplay: false
31834 * });
31835 *
31836 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
31837 * @return {Ext.dom.Element} The Element
31838 */\r
31839 puff: function(obj) {\r
31840 var me = this,\r
31841 dom = me.dom,\r
31842 beforeAnim,\r
31843 box = me.getBox(),\r
31844 originalStyles = me.getStyle([\r
31845 'width',\r
31846 'height',\r
31847 'left',\r
31848 'right',\r
31849 'top',\r
31850 'bottom',\r
31851 'position',\r
31852 'z-index',\r
31853 'font-size',\r
31854 'opacity'\r
31855 ], true);\r
31856 obj = Ext.applyIf(obj || {}, {\r
31857 easing: 'ease-out',\r
31858 duration: 500,\r
31859 useDisplay: false\r
31860 });\r
31861 beforeAnim = function() {\r
31862 var el = Ext.fly(dom, '_anim');\r
31863 el.clearOpacity();\r
31864 el.show();\r
31865 this.to = {\r
31866 width: box.width * 2,\r
31867 height: box.height * 2,\r
31868 x: box.x - (box.width / 2),\r
31869 y: box.y - (box.height / 2),\r
31870 opacity: 0,\r
31871 fontSize: '200%'\r
31872 };\r
31873 this.on('afteranimate', function() {\r
31874 var el = Ext.fly(dom, '_anim');\r
31875 if (el) {\r
31876 if (obj.useDisplay) {\r
31877 el.setDisplayed(false);\r
31878 } else {\r
31879 el.hide();\r
31880 }\r
31881 el.setStyle(originalStyles);\r
31882 Ext.callback(obj.callback, obj.scope);\r
31883 }\r
31884 });\r
31885 };\r
31886 me.animate({\r
31887 duration: obj.duration,\r
31888 easing: obj.easing,\r
31889 listeners: {\r
31890 beforeanimate: {\r
31891 fn: beforeAnim\r
31892 }\r
31893 }\r
31894 });\r
31895 return me;\r
31896 },\r
31897 /**
31898 * Enable text selection for this element (normalized across browsers)
31899 * @return {Ext.dom.Element} this
31900 */\r
31901 selectable: function() {\r
31902 var me = this;\r
31903 // We clear this property for all browsers, not just Opera. This is so that rendering templates don't need to\r
31904 // condition on Opera when making elements unselectable.\r
31905 me.dom.unselectable = '';\r
31906 me.removeCls(Element.unselectableCls);\r
31907 me.addCls(Element.selectableCls);\r
31908 return me;\r
31909 },\r
31910 // private\r
31911 // used to ensure the mouseup event is captured if it occurs outside of the\r
31912 // window in IE9m. The only reason this method exists, (vs just calling\r
31913 // el.dom.setCapture() directly) is so that we can override it to emptyFn\r
31914 // during testing because setCapture() can wreak havoc on emulated mouse events\r
31915 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms646262(v=vs.85).aspx\r
31916 setCapture: function() {\r
31917 var dom = this.dom;\r
31918 if (Ext.isIE9m && dom.setCapture) {\r
31919 dom.setCapture();\r
31920 }\r
31921 },\r
31922 /**
31923 * Set the height of this Element.
31924 *
31925 * // change the height to 200px and animate with default configuration
31926 * Ext.fly('elementId').setHeight(200, true);
31927 *
31928 * // change the height to 150px and animate with a custom configuration
31929 * Ext.fly('elId').setHeight(150, {
31930 * duration : 500, // animation will have a duration of .5 seconds
31931 * // will change the content to "finished"
31932 * callback: function(){ this.{@link #setHtml}("finished"); }
31933 * });
31934 *
31935 * @param {Number/String} height The new height. This may be one of:
31936 *
31937 * - A Number specifying the new height in pixels.
31938 * - A String used to set the CSS height style. Animation may **not** be used.
31939 *
31940 * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
31941 * the default animation (`{duration: 350, easing: 'ease-in'}`)
31942 * @return {Ext.dom.Element} this
31943 */\r
31944 setHeight: function(height, animate) {\r
31945 var me = this;\r
31946 if (!animate || !me.anim) {\r
31947 me.callParent(arguments);\r
31948 } else {\r
31949 if (!Ext.isObject(animate)) {\r
31950 animate = {};\r
31951 }\r
31952 me.animate(Ext.applyIf({\r
31953 to: {\r
31954 height: height\r
31955 }\r
31956 }, animate));\r
31957 }\r
31958 return me;\r
31959 },\r
31960 /**
31961 * Removes "vertical" state from this element (reverses everything done
31962 * by {@link #setVertical}).
31963 * @private
31964 */\r
31965 setHorizontal: function() {\r
31966 var me = this,\r
31967 cls = me.verticalCls;\r
31968 delete me.vertical;\r
31969 if (cls) {\r
31970 delete me.verticalCls;\r
31971 me.removeCls(cls);\r
31972 }\r
31973 // delete the inverted methods and revert to inheriting from the prototype \r
31974 delete me.setWidth;\r
31975 delete me.setHeight;\r
31976 if (!Ext.isIE8) {\r
31977 delete me.getWidth;\r
31978 delete me.getHeight;\r
31979 }\r
31980 // revert to inheriting styleHooks from the prototype\r
31981 delete me.styleHooks;\r
31982 },\r
31983 /**
31984 * Updates the *text* value of this element.
31985 * Replaces the content of this element with a *single text node* containing the passed text.
31986 * @param {String} text The text to display in this Element.
31987 */\r
31988 updateText: function(text) {\r
31989 var me = this,\r
31990 dom, textNode;\r
31991 if (dom) {\r
31992 textNode = dom.firstChild;\r
31993 if (!textNode || (textNode.nodeType !== 3 || textNode.nextSibling)) {\r
31994 textNode = DOC.createTextNode();\r
31995 me.empty();\r
31996 dom.appendChild(textNode);\r
31997 }\r
31998 if (text) {\r
31999 textNode.data = text;\r
32000 }\r
32001 }\r
32002 },\r
32003 /**
32004 * Updates the innerHTML of this element, optionally searching for and processing scripts.
32005 * @param {String} html The new HTML
32006 * @param {Boolean} [loadScripts] Pass `true` to look for and process scripts.
32007 * @param {Function} [callback] For async script loading you can be notified when the update completes.
32008 * @param {Object} [scope=`this`] The scope (`this` reference) in which to execute the callback.
32009 *
32010 * Also used as the scope for any *inline* script source if the `loadScripts` parameter is `true`.
32011 * Scripts with a `src` attribute cannot be executed in this scope.
32012 *
32013 * Defaults to this Element.
32014 * @return {Ext.dom.Element} this
32015 */\r
32016 setHtml: function(html, loadScripts, callback, scope) {\r
32017 var me = this,\r
32018 id, dom, interval;\r
32019 if (!me.dom) {\r
32020 return me;\r
32021 }\r
32022 html = html || '';\r
32023 dom = me.dom;\r
32024 if (loadScripts !== true) {\r
32025 dom.innerHTML = html;\r
32026 Ext.callback(callback, me);\r
32027 return me;\r
32028 }\r
32029 id = Ext.id();\r
32030 html += '<span id="' + id + '" role="presentation"></span>';\r
32031 interval = Ext.interval(function() {\r
32032 var hd, match, attrs, srcMatch, typeMatch, el, s;\r
32033 if (!(el = DOC.getElementById(id))) {\r
32034 return false;\r
32035 }\r
32036 clearInterval(interval);\r
32037 Ext.removeNode(el);\r
32038 hd = Ext.getHead().dom;\r
32039 while ((match = scriptTagRe.exec(html))) {\r
32040 attrs = match[1];\r
32041 srcMatch = attrs ? attrs.match(srcRe) : false;\r
32042 if (srcMatch && srcMatch[2]) {\r
32043 s = DOC.createElement("script");\r
32044 s.src = srcMatch[2];\r
32045 typeMatch = attrs.match(typeRe);\r
32046 if (typeMatch && typeMatch[2]) {\r
32047 s.type = typeMatch[2];\r
32048 }\r
32049 hd.appendChild(s);\r
32050 } else if (match[2] && match[2].length > 0) {\r
32051 if (scope) {\r
32052 Ext.functionFactory(match[2]).call(scope);\r
32053 } else {\r
32054 Ext.globalEval(match[2]);\r
32055 }\r
32056 }\r
32057 }\r
32058 Ext.callback(callback, scope || me);\r
32059 }, 20);\r
32060 dom.innerHTML = html.replace(replaceScriptTagRe, '');\r
32061 return me;\r
32062 },\r
32063 /**
32064 * Set the opacity of the element
32065 * @param {Number} opacity The new opacity. 0 = transparent, .5 = 50% visible, 1 = fully visible, etc
32066 * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
32067 * the default animation (`{duration: 350, easing: 'ease-in'}`)
32068 * @return {Ext.dom.Element} this
32069 */\r
32070 setOpacity: function(opacity, animate) {\r
32071 var me = this;\r
32072 if (!me.dom) {\r
32073 return me;\r
32074 }\r
32075 if (!animate || !me.anim) {\r
32076 me.setStyle('opacity', opacity);\r
32077 } else {\r
32078 if (typeof animate != 'object') {\r
32079 animate = {\r
32080 duration: 350,\r
32081 easing: 'ease-in'\r
32082 };\r
32083 }\r
32084 me.animate(Ext.applyIf({\r
32085 to: {\r
32086 opacity: opacity\r
32087 }\r
32088 }, animate));\r
32089 }\r
32090 return me;\r
32091 },\r
32092 /**
32093 * Set positioning with an object returned by #getPositioning.
32094 * @param {Object} posCfg
32095 * @return {Ext.dom.Element} this
32096 */\r
32097 setPositioning: function(pc) {\r
32098 return this.setStyle(pc);\r
32099 },\r
32100 /**
32101 * Changes this Element's state to "vertical" (rotated 90 or 270 degrees).
32102 * This involves inverting the getters and setters for height and width,
32103 * and applying hooks for rotating getters and setters for border/margin/padding.
32104 * (getWidth becomes getHeight and vice versa), setStyle and getStyle will
32105 * also return the inverse when height or width are being operated on.
32106 *
32107 * @param {Number} angle the angle of rotation - either 90 or 270
32108 * @param {String} cls an optional css class that contains the required
32109 * styles for switching the element to vertical orientation. Omit this if
32110 * the element already contains vertical styling. If cls is provided,
32111 * it will be removed from the element when {@link #setHorizontal} is called.
32112 * @private
32113 */\r
32114 setVertical: function(angle, cls) {\r
32115 var me = this,\r
32116 proto = Element.prototype;\r
32117 me.vertical = true;\r
32118 if (cls) {\r
32119 me.addCls(me.verticalCls = cls);\r
32120 }\r
32121 me.setWidth = proto.setHeight;\r
32122 me.setHeight = proto.setWidth;\r
32123 if (!Ext.isIE8) {\r
32124 // In browsers that use CSS3 transforms we must invert getHeight and\r
32125 // get Width. In IE8 no adjustment is needed because we use\r
32126 // a BasicImage filter to rotate the element and the element's\r
32127 // offsetWidth and offsetHeight are automatically inverted.\r
32128 me.getWidth = proto.getHeight;\r
32129 me.getHeight = proto.getWidth;\r
32130 }\r
32131 // Switch to using the appropriate vertical style hooks\r
32132 me.styleHooks = (angle === 270) ? proto.verticalStyleHooks270 : proto.verticalStyleHooks90;\r
32133 },\r
32134 /**
32135 * Set the size of this Element. If animation is true, both width and height will be animated concurrently.
32136 * @param {Number/String} width The new width. This may be one of:
32137 *
32138 * - A Number specifying the new width in pixels.
32139 * - A String used to set the CSS width style. Animation may **not** be used.
32140 * - A size object in the format `{width: widthValue, height: heightValue}`.
32141 *
32142 * @param {Number/String} height The new height. This may be one of:
32143 *
32144 * - A Number specifying the new height in pixels.
32145 * - A String used to set the CSS height style. Animation may **not** be used.
32146 *
32147 * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
32148 * the default animation (`{duration: 350, easing: 'ease-in'}`)
32149 *
32150 * @return {Ext.dom.Element} this
32151 */\r
32152 setSize: function(width, height, animate) {\r
32153 var me = this;\r
32154 if (Ext.isObject(width)) {\r
32155 // in case of object from getSize()\r
32156 animate = height;\r
32157 height = width.height;\r
32158 width = width.width;\r
32159 }\r
32160 if (!animate || !me.anim) {\r
32161 me.dom.style.width = Element.addUnits(width);\r
32162 me.dom.style.height = Element.addUnits(height);\r
32163 if (me.shadow || me.shim) {\r
32164 me.syncUnderlays();\r
32165 }\r
32166 } else {\r
32167 if (animate === true) {\r
32168 animate = {};\r
32169 }\r
32170 me.animate(Ext.applyIf({\r
32171 to: {\r
32172 width: width,\r
32173 height: height\r
32174 }\r
32175 }, animate));\r
32176 }\r
32177 return me;\r
32178 },\r
32179 /**
32180 * Sets the visibility of the element (see details). If the visibilityMode is set
32181 * to Element.DISPLAY, it will use the display property to hide the element,
32182 * otherwise it uses visibility. The default is to hide and show using the
32183 * visibility property.
32184 *
32185 * @param {Boolean} visible Whether the element is visible
32186 * @param {Boolean/Object} [animate] True for the default animation,
32187 * or a standard Element animation config object.
32188 *
32189 * @return {Ext.dom.Element} this
32190 */\r
32191 setVisible: function(visible, animate) {\r
32192 var me = this,\r
32193 dom = me.dom,\r
32194 visMode = getVisMode(me);\r
32195 // hideMode string override\r
32196 if (typeof animate === 'string') {\r
32197 switch (animate) {\r
32198 case DISPLAY:\r
32199 visMode = Element.DISPLAY;\r
32200 break;\r
32201 case VISIBILITY:\r
32202 visMode = Element.VISIBILITY;\r
32203 break;\r
32204 case OFFSETS:\r
32205 visMode = Element.OFFSETS;\r
32206 break;\r
32207 case CLIP:\r
32208 visMode = Element.CLIP;\r
32209 break;\r
32210 }\r
32211 me.setVisibilityMode(visMode);\r
32212 animate = false;\r
32213 }\r
32214 if (!animate || !me.anim) {\r
32215 if (visMode === Element.DISPLAY) {\r
32216 return me.setDisplayed(visible);\r
32217 } else if (visMode === Element.OFFSETS) {\r
32218 me[visible ? 'removeCls' : 'addCls'](OFFSETCLASS);\r
32219 } else if (visMode === Element.CLIP) {\r
32220 me[visible ? 'removeCls' : 'addCls'](CLIPCLASS);\r
32221 } else if (visMode === Element.VISIBILITY) {\r
32222 me.fixDisplay();\r
32223 // Show by clearing visibility style. Explicitly setting to "visible" overrides parent visibility setting\r
32224 dom.style.visibility = visible ? '' : HIDDEN;\r
32225 }\r
32226 } else {\r
32227 // closure for composites\r
32228 if (visible) {\r
32229 me.setOpacity(0.01);\r
32230 me.setVisible(true);\r
32231 }\r
32232 if (!Ext.isObject(animate)) {\r
32233 animate = {\r
32234 duration: 350,\r
32235 easing: 'ease-in'\r
32236 };\r
32237 }\r
32238 me.animate(Ext.applyIf({\r
32239 callback: function() {\r
32240 if (!visible) {\r
32241 // Grab the dom again, since the reference may have changed if we use fly\r
32242 Ext.fly(dom).setVisible(false).setOpacity(1);\r
32243 }\r
32244 },\r
32245 to: {\r
32246 opacity: (visible) ? 1 : 0\r
32247 }\r
32248 }, animate));\r
32249 }\r
32250 me.getData()[ISVISIBLE] = visible;\r
32251 if (me.shadow || me.shim) {\r
32252 me.setUnderlaysVisible(visible);\r
32253 }\r
32254 return me;\r
32255 },\r
32256 /**
32257 * Set the width of this Element.
32258 *
32259 * // change the width to 200px and animate with default configuration
32260 * Ext.fly('elementId').setWidth(200, true);
32261 *
32262 * // change the width to 150px and animate with a custom configuration
32263 * Ext.fly('elId').setWidth(150, {
32264 * duration : 500, // animation will have a duration of .5 seconds
32265 * // will change the content to "finished"
32266 * callback: function(){ this.{@link #setHtml}("finished"); }
32267 * });
32268 *
32269 * @param {Number/String} width The new width. This may be one of:
32270 *
32271 * - A Number specifying the new width in pixels.
32272 * - A String used to set the CSS width style. Animation may **not** be used.
32273 *
32274 * @param {Boolean/Object} [animate] a standard Element animation config object or `true` for
32275 * the default animation (`{duration: 350, easing: 'ease-in'}`)
32276 * @return {Ext.dom.Element} this
32277 */\r
32278 setWidth: function(width, animate) {\r
32279 var me = this;\r
32280 if (!animate || !me.anim) {\r
32281 me.callParent(arguments);\r
32282 } else {\r
32283 if (!Ext.isObject(animate)) {\r
32284 animate = {};\r
32285 }\r
32286 me.animate(Ext.applyIf({\r
32287 to: {\r
32288 width: width\r
32289 }\r
32290 }, animate));\r
32291 }\r
32292 return me;\r
32293 },\r
32294 setX: function(x, animate) {\r
32295 return this.setXY([\r
32296 x,\r
32297 this.getY()\r
32298 ], animate);\r
32299 },\r
32300 setXY: function(xy, animate) {\r
32301 var me = this;\r
32302 if (!animate || !me.anim) {\r
32303 me.callParent([\r
32304 xy\r
32305 ]);\r
32306 } else {\r
32307 if (!Ext.isObject(animate)) {\r
32308 animate = {};\r
32309 }\r
32310 me.animate(Ext.applyIf({\r
32311 to: {\r
32312 x: xy[0],\r
32313 y: xy[1]\r
32314 }\r
32315 }, animate));\r
32316 }\r
32317 return this;\r
32318 },\r
32319 setY: function(y, animate) {\r
32320 return this.setXY([\r
32321 this.getX(),\r
32322 y\r
32323 ], animate);\r
32324 },\r
32325 /**
32326 * Show this element - Uses display mode to determine whether to use "display",
32327 * "visibility", "offsets", or "clip". See {@link #setVisible}.
32328 *
32329 * @param {Boolean/Object} [animate] true for the default animation or a standard
32330 * Element animation config object.
32331 *
32332 * @return {Ext.dom.Element} this
32333 */\r
32334 show: function(animate) {\r
32335 // hideMode override\r
32336 if (typeof animate === 'string') {\r
32337 this.setVisible(true, animate);\r
32338 return this;\r
32339 }\r
32340 this.setVisible(true, this.anim(animate));\r
32341 return this;\r
32342 },\r
32343 /**
32344 * Slides the element into view. An anchor point can be optionally passed to set the point of origin for the slide
32345 * effect. This function automatically handles wrapping the element with a fixed-size container if needed. See the
32346 * {@link Ext.fx.Anim} class overview for valid anchor point options. Usage:
32347 *
32348 * // default: slide the element in from the top
32349 * el.slideIn();
32350 *
32351 * // custom: slide the element in from the right with a 2-second duration
32352 * el.slideIn('r', { duration: 2000 });
32353 *
32354 * // common config options shown with default values
32355 * el.slideIn('t', {
32356 * easing: 'easeOut',
32357 * duration: 500
32358 * });
32359 *
32360 * @param {String} anchor (optional) One of the valid {@link Ext.fx.Anim} anchor positions (defaults to top: 't')
32361 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
32362 * @param {Boolean} options.preserveScroll Set to true if preservation of any descendant elements'
32363 * `scrollTop` values is required. By default the DOM wrapping operation performed by `slideIn` and
32364 * `slideOut` causes the browser to lose all scroll positions.
32365 * @return {Ext.dom.Element} The Element
32366 */\r
32367 slideIn: function(anchor, obj, slideOut) {\r
32368 var me = this,\r
32369 dom = me.dom,\r
32370 elStyle = dom.style,\r
32371 beforeAnim, wrapAnim, restoreScroll, wrapDomParentNode;\r
32372 anchor = anchor || "t";\r
32373 obj = obj || {};\r
32374 beforeAnim = function() {\r
32375 var animScope = this,\r
32376 listeners = obj.listeners,\r
32377 el = Ext.fly(dom, '_anim'),\r
32378 box, originalStyles, anim, wrap;\r
32379 if (!slideOut) {\r
32380 el.fixDisplay();\r
32381 }\r
32382 box = el.getBox();\r
32383 if ((anchor == 't' || anchor == 'b') && box.height === 0) {\r
32384 box.height = dom.scrollHeight;\r
32385 } else if ((anchor == 'l' || anchor == 'r') && box.width === 0) {\r
32386 box.width = dom.scrollWidth;\r
32387 }\r
32388 originalStyles = el.getStyle([\r
32389 'width',\r
32390 'height',\r
32391 'left',\r
32392 'right',\r
32393 'top',\r
32394 'bottom',\r
32395 'position',\r
32396 'z-index'\r
32397 ], true);\r
32398 el.setSize(box.width, box.height);\r
32399 // Cache all descendants' scrollTop & scrollLeft values if configured to preserve scroll.\r
32400 if (obj.preserveScroll) {\r
32401 restoreScroll = el.cacheScrollValues();\r
32402 }\r
32403 wrap = el.wrap({\r
32404 role: 'presentation',\r
32405 id: Ext.id() + '-anim-wrap-for-' + el.dom.id,\r
32406 style: {\r
32407 visibility: slideOut ? 'visible' : 'hidden'\r
32408 }\r
32409 });\r
32410 wrapDomParentNode = wrap.dom.parentNode;\r
32411 wrap.setPositioning(el.getPositioning());\r
32412 if (wrap.isStyle('position', 'static')) {\r
32413 wrap.position('relative');\r
32414 }\r
32415 el.clearPositioning('auto');\r
32416 wrap.clip();\r
32417 // The wrap will have reset all descendant scrollTops. Restore them if we cached them.\r
32418 if (restoreScroll) {\r
32419 restoreScroll();\r
32420 }\r
32421 // This element is temporarily positioned absolute within its wrapper.\r
32422 // Restore to its default, CSS-inherited visibility setting.\r
32423 // We cannot explicitly poke visibility:visible into its style because that overrides the visibility of the wrap.\r
32424 el.setStyle({\r
32425 visibility: '',\r
32426 position: 'absolute'\r
32427 });\r
32428 if (slideOut) {\r
32429 wrap.setSize(box.width, box.height);\r
32430 }\r
32431 switch (anchor) {\r
32432 case 't':\r
32433 anim = {\r
32434 from: {\r
32435 width: box.width + 'px',\r
32436 height: '0px'\r
32437 },\r
32438 to: {\r
32439 width: box.width + 'px',\r
32440 height: box.height + 'px'\r
32441 }\r
32442 };\r
32443 elStyle.bottom = '0px';\r
32444 break;\r
32445 case 'l':\r
32446 anim = {\r
32447 from: {\r
32448 width: '0px',\r
32449 height: box.height + 'px'\r
32450 },\r
32451 to: {\r
32452 width: box.width + 'px',\r
32453 height: box.height + 'px'\r
32454 }\r
32455 };\r
32456 me.anchorAnimX(anchor);\r
32457 break;\r
32458 case 'r':\r
32459 anim = {\r
32460 from: {\r
32461 x: box.x + box.width,\r
32462 width: '0px',\r
32463 height: box.height + 'px'\r
32464 },\r
32465 to: {\r
32466 x: box.x,\r
32467 width: box.width + 'px',\r
32468 height: box.height + 'px'\r
32469 }\r
32470 };\r
32471 me.anchorAnimX(anchor);\r
32472 break;\r
32473 case 'b':\r
32474 anim = {\r
32475 from: {\r
32476 y: box.y + box.height,\r
32477 width: box.width + 'px',\r
32478 height: '0px'\r
32479 },\r
32480 to: {\r
32481 y: box.y,\r
32482 width: box.width + 'px',\r
32483 height: box.height + 'px'\r
32484 }\r
32485 };\r
32486 break;\r
32487 case 'tl':\r
32488 anim = {\r
32489 from: {\r
32490 x: box.x,\r
32491 y: box.y,\r
32492 width: '0px',\r
32493 height: '0px'\r
32494 },\r
32495 to: {\r
32496 width: box.width + 'px',\r
32497 height: box.height + 'px'\r
32498 }\r
32499 };\r
32500 elStyle.bottom = '0px';\r
32501 me.anchorAnimX('l');\r
32502 break;\r
32503 case 'bl':\r
32504 anim = {\r
32505 from: {\r
32506 y: box.y + box.height,\r
32507 width: '0px',\r
32508 height: '0px'\r
32509 },\r
32510 to: {\r
32511 y: box.y,\r
32512 width: box.width + 'px',\r
32513 height: box.height + 'px'\r
32514 }\r
32515 };\r
32516 me.anchorAnimX('l');\r
32517 break;\r
32518 case 'br':\r
32519 anim = {\r
32520 from: {\r
32521 x: box.x + box.width,\r
32522 y: box.y + box.height,\r
32523 width: '0px',\r
32524 height: '0px'\r
32525 },\r
32526 to: {\r
32527 x: box.x,\r
32528 y: box.y,\r
32529 width: box.width + 'px',\r
32530 height: box.height + 'px'\r
32531 }\r
32532 };\r
32533 me.anchorAnimX('r');\r
32534 break;\r
32535 case 'tr':\r
32536 anim = {\r
32537 from: {\r
32538 x: box.x + box.width,\r
32539 width: '0px',\r
32540 height: '0px'\r
32541 },\r
32542 to: {\r
32543 x: box.x,\r
32544 width: box.width + 'px',\r
32545 height: box.height + 'px'\r
32546 }\r
32547 };\r
32548 elStyle.bottom = '0px';\r
32549 me.anchorAnimX('r');\r
32550 break;\r
32551 }\r
32552 wrap.show();\r
32553 wrapAnim = Ext.apply({}, obj);\r
32554 delete wrapAnim.listeners;\r
32555 wrapAnim = new Ext.fx.Anim(Ext.applyIf(wrapAnim, {\r
32556 target: wrap,\r
32557 duration: 500,\r
32558 easing: 'ease-out',\r
32559 from: slideOut ? anim.to : anim.from,\r
32560 to: slideOut ? anim.from : anim.to\r
32561 }));\r
32562 // In the absence of a callback, this listener MUST be added first\r
32563 wrapAnim.on('afteranimate', function() {\r
32564 var el = Ext.fly(dom, '_anim');\r
32565 el.setStyle(originalStyles);\r
32566 if (slideOut) {\r
32567 if (obj.useDisplay) {\r
32568 el.setDisplayed(false);\r
32569 } else {\r
32570 el.hide();\r
32571 }\r
32572 }\r
32573 if (wrap.dom) {\r
32574 if (wrap.dom.parentNode) {\r
32575 wrap.dom.parentNode.insertBefore(el.dom, wrap.dom);\r
32576 } else {\r
32577 wrapDomParentNode.appendChild(el.dom);\r
32578 }\r
32579 wrap.destroy();\r
32580 }\r
32581 // The unwrap will have reset all descendant scrollTops. Restore them if we cached them.\r
32582 if (restoreScroll) {\r
32583 restoreScroll();\r
32584 }\r
32585 // kill the no-op element animation created below\r
32586 animScope.end();\r
32587 });\r
32588 // Add configured listeners after\r
32589 if (listeners) {\r
32590 wrapAnim.on(listeners);\r
32591 }\r
32592 };\r
32593 me.animate({\r
32594 // See "A Note About Wrapped Animations" at the top of this class:\r
32595 duration: obj.duration ? Math.max(obj.duration, 500) * 2 : 1000,\r
32596 listeners: {\r
32597 beforeanimate: beforeAnim\r
32598 }\r
32599 });\r
32600 // kick off the wrap animation\r
32601 return me;\r
32602 },\r
32603 /**
32604 * Slides the element out of view. An anchor point can be optionally passed to set the end point for the slide
32605 * effect. When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will
32606 * still take up space in the document. The element must be removed from the DOM using the 'remove' config option if
32607 * desired. This function automatically handles wrapping the element with a fixed-size container if needed. See the
32608 * {@link Ext.fx.Anim} class overview for valid anchor point options. Usage:
32609 *
32610 * // default: slide the element out to the top
32611 * el.slideOut();
32612 *
32613 * // custom: slide the element out to the right with a 2-second duration
32614 * el.slideOut('r', { duration: 2000 });
32615 *
32616 * // common config options shown with default values
32617 * el.slideOut('t', {
32618 * easing: 'easeOut',
32619 * duration: 500,
32620 * remove: false,
32621 * useDisplay: false
32622 * });
32623 *
32624 * @param {String} anchor (optional) One of the valid {@link Ext.fx.Anim} anchor positions (defaults to top: 't')
32625 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
32626 * @return {Ext.dom.Element} The Element
32627 */\r
32628 slideOut: function(anchor, o) {\r
32629 return this.slideIn(anchor, o, true);\r
32630 },\r
32631 /**
32632 * Stops the specified event(s) from bubbling and optionally prevents the default action
32633 *
32634 * var store = Ext.create('Ext.data.Store', {
32635 * fields: ['name', 'email'],
32636 * data: [{
32637 * 'name': 'Finn',
32638 * "email": "finn@adventuretime.com"
32639 * }]
32640 * });
32641 *
32642 * Ext.create('Ext.grid.Panel', {
32643 * title: 'Land of Ooo',
32644 * store: store,
32645 * columns: [{
32646 * text: 'Name',
32647 * dataIndex: 'name'
32648 * }, {
32649 * text: 'Email <img style="vertical-align:middle;" src="{some-help-image-src}" />',
32650 * dataIndex: 'email',
32651 * flex: 1,
32652 * listeners: {
32653 * render: function(col) {
32654 * // Swallow the click event when the click occurs on the
32655 * // help icon - preventing the sorting of data by that
32656 * // column and instead performing an action specific to
32657 * // the help icon
32658 * var img = col.getEl().down('img');
32659 * img.swallowEvent(['click', 'mousedown'], true);
32660 * col.on('click', function() {
32661 * // logic to show a help dialog
32662 * console.log('image click handler');
32663 * }, col);
32664 * }
32665 * }
32666 * }],
32667 * height: 200,
32668 * width: 400,
32669 * renderTo: document.body
32670 * });
32671 *
32672 * @param {String/String[]} eventName an event / array of events to stop from bubbling
32673 * @param {Boolean} [preventDefault] true to prevent the default action too
32674 * @return {Ext.dom.Element} this
32675 */\r
32676 swallowEvent: function(eventName, preventDefault) {\r
32677 var me = this,\r
32678 e, eLen,\r
32679 fn = function(e) {\r
32680 e.stopPropagation();\r
32681 if (preventDefault) {\r
32682 e.preventDefault();\r
32683 }\r
32684 };\r
32685 if (Ext.isArray(eventName)) {\r
32686 eLen = eventName.length;\r
32687 for (e = 0; e < eLen; e++) {\r
32688 me.on(eventName[e], fn);\r
32689 }\r
32690 return me;\r
32691 }\r
32692 me.on(eventName, fn);\r
32693 return me;\r
32694 },\r
32695 /**
32696 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
32697 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
32698 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if
32699 * desired. Usage:
32700 *
32701 * // default
32702 * el.switchOff();
32703 *
32704 * // all config options shown with default values
32705 * el.switchOff({
32706 * easing: 'easeIn',
32707 * duration: .3,
32708 * remove: false,
32709 * useDisplay: false
32710 * });
32711 *
32712 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
32713 * @return {Ext.dom.Element} The Element
32714 */\r
32715 switchOff: function(obj) {\r
32716 var me = this,\r
32717 dom = me.dom,\r
32718 beforeAnim;\r
32719 obj = Ext.applyIf(obj || {}, {\r
32720 easing: 'ease-in',\r
32721 duration: 500,\r
32722 remove: false,\r
32723 useDisplay: false\r
32724 });\r
32725 beforeAnim = function() {\r
32726 var el = Ext.fly(dom, '_anim'),\r
32727 animScope = this,\r
32728 size = el.getSize(),\r
32729 xy = el.getXY(),\r
32730 keyframe, position;\r
32731 el.clearOpacity();\r
32732 el.clip();\r
32733 position = el.getPositioning();\r
32734 keyframe = new Ext.fx.Animator({\r
32735 target: dom,\r
32736 duration: obj.duration,\r
32737 easing: obj.easing,\r
32738 keyframes: {\r
32739 33: {\r
32740 opacity: 0.3\r
32741 },\r
32742 66: {\r
32743 height: 1,\r
32744 y: xy[1] + size.height / 2\r
32745 },\r
32746 100: {\r
32747 width: 1,\r
32748 x: xy[0] + size.width / 2\r
32749 }\r
32750 }\r
32751 });\r
32752 keyframe.on('afteranimate', function() {\r
32753 var el = Ext.fly(dom, '_anim');\r
32754 if (obj.useDisplay) {\r
32755 el.setDisplayed(false);\r
32756 } else {\r
32757 el.hide();\r
32758 }\r
32759 el.clearOpacity();\r
32760 el.setPositioning(position);\r
32761 el.setSize(size);\r
32762 // kill the no-op element animation created below\r
32763 animScope.end();\r
32764 });\r
32765 };\r
32766 me.animate({\r
32767 // See "A Note About Wrapped Animations" at the top of this class:\r
32768 duration: (Math.max(obj.duration, 500) * 2),\r
32769 listeners: {\r
32770 beforeanimate: {\r
32771 fn: beforeAnim\r
32772 }\r
32773 },\r
32774 callback: obj.callback,\r
32775 scope: obj.scope\r
32776 });\r
32777 return me;\r
32778 },\r
32779 /**
32780 * @private.
32781 * Currently used for updating grid cells without modifying DOM structure
32782 *
32783 * Synchronizes content of this Element with the content of the passed element.
32784 *
32785 * Style and CSS class are copied from source into this Element, and contents are synced
32786 * recursively. If a child node is a text node, the textual data is copied.
32787 */\r
32788 syncContent: function(source) {\r
32789 source = Ext.getDom(source);\r
32790 var sourceNodes = source.childNodes,\r
32791 sourceLen = sourceNodes.length,\r
32792 dest = this.dom,\r
32793 destNodes = dest.childNodes,\r
32794 destLen = destNodes.length,\r
32795 i, destNode, sourceNode, nodeType, newAttrs, attLen, attName,\r
32796 elData = dest._extData;\r
32797 // Copy top node's attributes across. Use IE-specific method if possible.\r
32798 // In IE10, there is a problem where the className will not get updated\r
32799 // in the view, even though the className on the dom element is correct.\r
32800 // See EXTJSIV-9462\r
32801 if (Ext.isIE9m && dest.mergeAttributes) {\r
32802 dest.mergeAttributes(source, true);\r
32803 // EXTJSIV-6803. IE's mergeAttributes appears not to make the source's "src" value available until after the image is ready.\r
32804 // So programmatically copy any src attribute.\r
32805 dest.src = source.src;\r
32806 } else {\r
32807 newAttrs = source.attributes;\r
32808 attLen = newAttrs.length;\r
32809 for (i = 0; i < attLen; i++) {\r
32810 attName = newAttrs[i].name;\r
32811 if (attName !== 'id') {\r
32812 dest.setAttribute(attName, newAttrs[i].value);\r
32813 }\r
32814 }\r
32815 }\r
32816 // The element's data is no longer synchronized. We just overwrite it in the DOM\r
32817 if (elData) {\r
32818 elData.isSynchronized = false;\r
32819 }\r
32820 // If the number of child nodes does not match, fall back to replacing innerHTML\r
32821 if (sourceLen !== destLen) {\r
32822 dest.innerHTML = source.innerHTML;\r
32823 return;\r
32824 }\r
32825 // Loop through source nodes.\r
32826 // If there are fewer, we must remove excess\r
32827 for (i = 0; i < sourceLen; i++) {\r
32828 sourceNode = sourceNodes[i];\r
32829 destNode = destNodes[i];\r
32830 nodeType = sourceNode.nodeType;\r
32831 // If node structure is out of sync, just drop innerHTML in and return\r
32832 if (nodeType !== destNode.nodeType || (nodeType === 1 && sourceNode.tagName !== destNode.tagName)) {\r
32833 dest.innerHTML = source.innerHTML;\r
32834 return;\r
32835 }\r
32836 // Update text node\r
32837 if (nodeType === 3) {\r
32838 destNode.data = sourceNode.data;\r
32839 } else // Sync element content\r
32840 {\r
32841 if (sourceNode.id && destNode.id !== sourceNode.id) {\r
32842 destNode.id = sourceNode.id;\r
32843 }\r
32844 destNode.style.cssText = sourceNode.style.cssText;\r
32845 destNode.className = sourceNode.className;\r
32846 Ext.fly(destNode, '_syncContent').syncContent(sourceNode);\r
32847 }\r
32848 }\r
32849 },\r
32850 /**
32851 * Toggles the element's visibility, depending on visibility mode.
32852 * @param {Boolean/Object} [animate] True for the default animation, or a standard Element animation config object
32853 * @return {Ext.dom.Element} this
32854 */\r
32855 toggle: function(animate) {\r
32856 var me = this;\r
32857 me.setVisible(!me.isVisible(), me.anim(animate));\r
32858 return me;\r
32859 },\r
32860 /**
32861 * Hides a previously applied mask.
32862 */\r
32863 unmask: function() {\r
32864 var me = this,\r
32865 data = me.getData(),\r
32866 maskEl = data.maskEl,\r
32867 style;\r
32868 if (maskEl) {\r
32869 style = maskEl.dom.style;\r
32870 // Remove resource-intensive CSS expressions as soon as they are not required.\r
32871 if (style.clearExpression) {\r
32872 style.clearExpression('width');\r
32873 style.clearExpression('height');\r
32874 }\r
32875 if (maskEl) {\r
32876 maskEl.destroy();\r
32877 delete data.maskEl;\r
32878 }\r
32879 me.removeCls([\r
32880 XMASKED,\r
32881 XMASKEDRELATIVE\r
32882 ]);\r
32883 }\r
32884 me.restoreTabbableState(me.dom === DOC.body);\r
32885 },\r
32886 /**
32887 * Return clipping (overflow) to original clipping before {@link #clip} was called
32888 * @return {Ext.dom.Element} this
32889 */\r
32890 unclip: function() {\r
32891 var me = this,\r
32892 data = me.getData(),\r
32893 clip;\r
32894 if (data[ISCLIPPED]) {\r
32895 data[ISCLIPPED] = false;\r
32896 clip = data[ORIGINALCLIP];\r
32897 if (clip.o) {\r
32898 me.setStyle(OVERFLOW, clip.o);\r
32899 }\r
32900 if (clip.x) {\r
32901 me.setStyle(OVERFLOWX, clip.x);\r
32902 }\r
32903 if (clip.y) {\r
32904 me.setStyle(OVERFLOWY, clip.y);\r
32905 }\r
32906 }\r
32907 return me;\r
32908 },\r
32909 translate: function(x, y, z) {\r
32910 if (Ext.supports.CssTransforms && !Ext.isIE9m) {\r
32911 this.callParent(arguments);\r
32912 } else {\r
32913 if (x != null) {\r
32914 this.dom.style.left = x + 'px';\r
32915 }\r
32916 if (y != null) {\r
32917 this.dom.style.top = y + 'px';\r
32918 }\r
32919 }\r
32920 },\r
32921 /**
32922 * Disables text selection for this element (normalized across browsers)
32923 * @return {Ext.dom.Element} this
32924 */\r
32925 unselectable: function() {\r
32926 // The approach used to disable text selection combines CSS, HTML attributes and DOM events. Importantly the\r
32927 // strategy is designed to be expressible in markup, so that elements can be rendered unselectable without\r
32928 // needing modifications post-render. e.g.:\r
32929 //\r
32930 // <div class="x-unselectable" unselectable="on"></div>\r
32931 //\r
32932 // Changes to this method may need to be reflected elsewhere, e.g. ProtoElement.\r
32933 var me = this;\r
32934 // The unselectable property (or similar) is supported by various browsers but Opera is the only browser that\r
32935 // doesn't support any of the other techniques. The problem with it is that it isn't inherited by child\r
32936 // elements. Theoretically we could add it to all children but the performance would be terrible. In certain\r
32937 // key locations (e.g. panel headers) we add unselectable="on" to extra elements during rendering just for\r
32938 // Opera's benefit.\r
32939 if (Ext.isOpera) {\r
32940 me.dom.unselectable = 'on';\r
32941 }\r
32942 // In Mozilla and WebKit the CSS properties -moz-user-select and -webkit-user-select prevent a selection\r
32943 // originating in an element. These are inherited, which is what we want.\r
32944 //\r
32945 // In IE we rely on a listener for the selectstart event instead. We don't need to register a listener on the\r
32946 // individual element, instead we use a single listener and rely on event propagation to listen for the event at\r
32947 // the document level. That listener will walk up the DOM looking for nodes that have either of the classes\r
32948 // x-selectable or x-unselectable. This simulates the CSS inheritance approach.\r
32949 //\r
32950 // IE 10 is expected to support -ms-user-select so the listener may not be required.\r
32951 me.removeCls(Element.selectableCls);\r
32952 me.addCls(Element.unselectableCls);\r
32953 return me;\r
32954 },\r
32955 privates: {\r
32956 /**
32957 * @private
32958 */\r
32959 findTabbableElements: function(options) {\r
32960 var skipSelf, skipChildren, excludeRoot, includeSaved, includeHidden,\r
32961 dom = this.dom,\r
32962 cAttr = Ext.Element.tabbableSavedCounterAttribute,\r
32963 selection = [],\r
32964 idx = 0,\r
32965 nodes, node, fly, i, len, tabIndex;\r
32966 if (!dom) {\r
32967 return selection;\r
32968 }\r
32969 if (options) {\r
32970 skipSelf = options.skipSelf;\r
32971 skipChildren = options.skipChildren;\r
32972 excludeRoot = options.excludeRoot;\r
32973 includeSaved = options.includeSaved;\r
32974 includeHidden = options.includeHidden;\r
32975 }\r
32976 excludeRoot = excludeRoot && Ext.getDom(excludeRoot);\r
32977 if (excludeRoot && excludeRoot.contains(dom)) {\r
32978 return selection;\r
32979 }\r
32980 if (!skipSelf && ((includeSaved && dom.hasAttribute(cAttr)) || this.isTabbable(includeHidden))) {\r
32981 selection[idx++] = dom;\r
32982 }\r
32983 if (skipChildren) {\r
32984 return selection;\r
32985 }\r
32986 nodes = dom.querySelectorAll(Ext.Element.tabbableSelector);\r
32987 len = nodes.length;\r
32988 if (!len) {\r
32989 return selection;\r
32990 }\r
32991 fly = new Ext.dom.Fly();\r
32992 // We're only interested in the elements that an user can *tab into*,\r
32993 // not all programmatically focusable elements. So we have to filter\r
32994 // these out.\r
32995 for (i = 0; i < len; i++) {\r
32996 node = nodes[i];\r
32997 // A node with tabIndex < 0 absolutely can't be tabbable\r
32998 // so we can save a function call if that is the case.\r
32999 // Note that we can't use node.tabIndex here because IE\r
33000 // will return 0 for elements that have no tabindex\r
33001 // attribute defined, regardless of whether they are\r
33002 // tabbable or not.\r
33003 tabIndex = +node.getAttribute('tabIndex');\r
33004 // quicker than parseInt\r
33005 // tabIndex value may be null for nodes with no tabIndex defined;\r
33006 // most of those may be naturally tabbable. We don't want to\r
33007 // check this here, that's isTabbable()'s job and it's not trivial.\r
33008 // We explicitly check that tabIndex is not negative. The expression\r
33009 // below is purposeful if hairy; this is a very hot code path so care\r
33010 // is taken to minimize the amount of DOM calls that could be avoided.\r
33011 // A node may have its tabindex saved by previous calls to\r
33012 // saveTabbableState(); in that case we need to return that node\r
33013 // so that its saved counter could be properly incremented or\r
33014 // decremented.\r
33015 if (((includeSaved && node.hasAttribute(cAttr)) || (!(tabIndex < 0) && fly.attach(node).isTabbable(includeHidden))) && !(excludeRoot && (excludeRoot === node || excludeRoot.contains(node)))) {\r
33016 selection[idx++] = node;\r
33017 }\r
33018 }\r
33019 return selection;\r
33020 },\r
33021 /**
33022 * @private
33023 */\r
33024 saveTabbableState: function(options) {\r
33025 var counterAttr = Ext.Element.tabbableSavedCounterAttribute,\r
33026 savedAttr = Ext.Element.tabbableSavedValueAttribute,\r
33027 counter, nodes, node, i, len;\r
33028 // By default include already saved tabbables, and just increase their save counter.\r
33029 // For example, if a View with saved tabbables is covered by a modal Window, saveTabbableState\r
33030 // Must disable tabbability for the whole document. But upon unmask, the View must not\r
33031 // be restored to tabbability. It must only have its save level decremented.\r
33032 // AbstractView#toggleChildrenTabbability however pases this as false so that\r
33033 // it may be called upon row add and it does not increment save levels on already saved tabbables.\r
33034 if (!options || options.includeSaved == null) {\r
33035 options = Ext.Object.chain(options || null);\r
33036 options.includeSaved = true;\r
33037 }\r
33038 nodes = this.findTabbableElements(options);\r
33039 for (i = 0 , len = nodes.length; i < len; i++) {\r
33040 node = nodes[i];\r
33041 counter = +node.getAttribute(counterAttr);\r
33042 if (counter > 0) {\r
33043 node.setAttribute(counterAttr, ++counter);\r
33044 } else {\r
33045 // tabIndex could be set on both naturally tabbable and generic elements.\r
33046 // Either way we need to save it to restore later.\r
33047 if (node.hasAttribute('tabIndex')) {\r
33048 node.setAttribute(savedAttr, node.getAttribute('tabIndex'));\r
33049 } else // When no tabIndex is specified, that means a naturally tabbable element.\r
33050 {\r
33051 node.setAttribute(savedAttr, 'none');\r
33052 }\r
33053 // We disable the tabbable state by setting tabIndex to -1.\r
33054 // The element can still be focused programmatically though.\r
33055 node.setAttribute('tabIndex', '-1');\r
33056 node.setAttribute(counterAttr, '1');\r
33057 }\r
33058 }\r
33059 return nodes;\r
33060 },\r
33061 /**
33062 * @private
33063 */\r
33064 restoreTabbableState: function(skipSelf, skipChildren) {\r
33065 var dom = this.dom,\r
33066 counterAttr = Ext.Element.tabbableSavedCounterAttribute,\r
33067 savedAttr = Ext.Element.tabbableSavedValueAttribute,\r
33068 nodes = [],\r
33069 idx, counter, nodes, node, i, len;\r
33070 if (!dom) {\r
33071 return this;\r
33072 }\r
33073 if (!skipChildren) {\r
33074 nodes = Ext.Array.from(dom.querySelectorAll('[' + counterAttr + ']'));\r
33075 }\r
33076 if (!skipSelf) {\r
33077 nodes.unshift(dom);\r
33078 }\r
33079 for (i = 0 , len = nodes.length; i < len; i++) {\r
33080 node = nodes[i];\r
33081 if (!node.hasAttribute(counterAttr) || !node.hasAttribute(savedAttr)) {\r
33082 \r
33083 continue;\r
33084 }\r
33085 counter = +node.getAttribute(counterAttr);\r
33086 if (counter > 1) {\r
33087 node.setAttribute(counterAttr, --counter);\r
33088 \r
33089 continue;\r
33090 }\r
33091 idx = node.getAttribute(savedAttr);\r
33092 // That is a naturally tabbable element\r
33093 if (idx === 'none') {\r
33094 node.removeAttribute('tabIndex');\r
33095 } else {\r
33096 node.setAttribute('tabIndex', idx);\r
33097 }\r
33098 node.removeAttribute(savedAttr);\r
33099 node.removeAttribute(counterAttr);\r
33100 }\r
33101 return nodes;\r
33102 }\r
33103 },\r
33104 deprecated: {\r
33105 '4.0': {\r
33106 methods: {\r
33107 /**
33108 * Creates a pause before any subsequent queued effects begin. If there are no effects queued after the pause it will
33109 * have no effect. Usage:
33110 *
33111 * el.pause(1);
33112 *
33113 * @deprecated 4.0 Use the `delay` config to {@link #animate} instead.
33114 * @param {Number} seconds The length of time to pause (in seconds)
33115 * @return {Ext.dom.Element} The Element
33116 */\r
33117 pause: function(ms) {\r
33118 var me = this;\r
33119 Ext.fx.Manager.setFxDefaults(me.id, {\r
33120 delay: ms\r
33121 });\r
33122 return me;\r
33123 },\r
33124 /**
33125 * Animates the transition of an element's dimensions from a starting height/width to an ending height/width. This
33126 * method is a convenience implementation of {@link #shift}. Usage:
33127 *
33128 * // change height and width to 100x100 pixels
33129 * el.scale(100, 100);
33130 *
33131 * // common config options shown with default values. The height and width will default to
33132 * // the element's existing values if passed as null.
33133 * el.scale(
33134 * [element's width],
33135 * [element's height], {
33136 * easing: 'easeOut',
33137 * duration: 350
33138 * }
33139 * );
33140 *
33141 * @deprecated 4.0 Just use {@link #animate} instead.
33142 * @param {Number} width The new width (pass undefined to keep the original width)
33143 * @param {Number} height The new height (pass undefined to keep the original height)
33144 * @param {Object} options (optional) Object literal with any of the {@link Ext.fx.Anim} config options
33145 * @return {Ext.dom.Element} The Element
33146 */\r
33147 scale: function(w, h, o) {\r
33148 this.animate(Ext.apply({}, o, {\r
33149 width: w,\r
33150 height: h\r
33151 }));\r
33152 return this;\r
33153 },\r
33154 /**
33155 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity. Any of these
33156 * properties not specified in the config object will not be changed. This effect requires that at least one new
33157 * dimension, position or opacity setting must be passed in on the config object in order for the function to have
33158 * any effect. Usage:
33159 *
33160 * // slide the element horizontally to x position 200 while changing the height and opacity
33161 * el.shift({ x: 200, height: 50, opacity: .8 });
33162 *
33163 * // common config options shown with default values.
33164 * el.shift({
33165 * width: [element's width],
33166 * height: [element's height],
33167 * x: [element's x position],
33168 * y: [element's y position],
33169 * opacity: [element's opacity],
33170 * easing: 'easeOut',
33171 * duration: 350
33172 * });
33173 *
33174 * @deprecated 4.0 Just use {@link #animate} instead.
33175 * @param {Object} options Object literal with any of the {@link Ext.fx.Anim} config options
33176 * @return {Ext.dom.Element} The Element
33177 */\r
33178 shift: function(config) {\r
33179 this.animate(config);\r
33180 return this;\r
33181 }\r
33182 }\r
33183 },\r
33184 '4.2': {\r
33185 methods: {\r
33186 /**
33187 * Sets the position of the element in page coordinates.
33188 * @param {Number} x X value for new position (coordinates are page-based)
33189 * @param {Number} y Y value for new position (coordinates are page-based)
33190 * @param {Boolean/Object} [animate] True for the default animation, or a standard
33191 * Element animation config object
33192 * @return {Ext.dom.Element} this
33193 * @deprecated 4.2.0 Use {@link Ext.dom.Element#setXY} instead.
33194 */\r
33195 moveTo: function(x, y, animate) {\r
33196 return this.setXY([\r
33197 x,\r
33198 y\r
33199 ], animate);\r
33200 },\r
33201 /**
33202 * Sets the element's position and size in one shot. If animation is true then
33203 * width, height, x and y will be animated concurrently.
33204 *
33205 * @param {Number} x X value for new position (coordinates are page-based)
33206 * @param {Number} y Y value for new position (coordinates are page-based)
33207 * @param {Number/String} width The new width. This may be one of:
33208 *
33209 * - A Number specifying the new width in pixels
33210 * - A String used to set the CSS width style. Animation may **not** be used.
33211 *
33212 * @param {Number/String} height The new height. This may be one of:
33213 *
33214 * - A Number specifying the new height in pixels
33215 * - A String used to set the CSS height style. Animation may **not** be used.
33216 *
33217 * @param {Boolean/Object} [animate] true for the default animation or
33218 * a standard Element animation config object
33219 *
33220 * @return {Ext.dom.Element} this
33221 * @deprecated 4.2.0 Use {@link Ext.util.Positionable#setBox} instead.
33222 */\r
33223 setBounds: function(x, y, width, height, animate) {\r
33224 return this.setBox({\r
33225 x: x,\r
33226 y: y,\r
33227 width: width,\r
33228 height: height\r
33229 }, animate);\r
33230 },\r
33231 /**
33232 * Sets the element's left and top positions directly using CSS style
33233 * @param {Number/String} left Number of pixels or CSS string value to
33234 * set as the left CSS property value
33235 * @param {Number/String} top Number of pixels or CSS string value to
33236 * set as the top CSS property value
33237 * @return {Ext.dom.Element} this
33238 * @deprecated 4.2.0 Use {@link Ext.dom.Element#setLocalXY} instead
33239 */\r
33240 setLeftTop: function(left, top) {\r
33241 var me = this,\r
33242 style = me.dom.style;\r
33243 style.left = Element.addUnits(left);\r
33244 style.top = Element.addUnits(top);\r
33245 if (me.shadow || me.shim) {\r
33246 me.syncUnderlays();\r
33247 }\r
33248 return me;\r
33249 },\r
33250 /**
33251 * Sets the position of the element in page coordinates.
33252 * @param {Number} x X value for new position
33253 * @param {Number} y Y value for new position
33254 * @param {Boolean/Object} [animate] True for the default animation, or a standard
33255 * Element animation config object
33256 * @return {Ext.dom.Element} this
33257 * @deprecated 4.2.0 Use {@link Ext.dom.Element#setXY} instead.
33258 */\r
33259 setLocation: function(x, y, animate) {\r
33260 return this.setXY([\r
33261 x,\r
33262 y\r
33263 ], animate);\r
33264 }\r
33265 }\r
33266 },\r
33267 '5.0': {\r
33268 methods: {\r
33269 /**
33270 * Returns the value of a namespaced attribute from the element's underlying DOM node.
33271 * @param {String} namespace The namespace in which to look for the attribute
33272 * @param {String} name The attribute name
33273 * @return {String} The attribute value
33274 * @deprecated 5.0.0 Please use {@link Ext.dom.Element#getAttribute} instead.
33275 */\r
33276 getAttributeNS: function(namespace, name) {\r
33277 return this.getAttribute(name, namespace);\r
33278 },\r
33279 /**
33280 * Calculates the x, y to center this element on the screen
33281 * @return {Number[]} The x, y values [x, y]
33282 * @deprecated 5.0.0 Use {@link Ext.dom.Element#getAlignToXY} instead.
33283 * el.getAlignToXY(document, 'c-c');
33284 */\r
33285 getCenterXY: function() {\r
33286 return this.getAlignToXY(DOC, 'c-c');\r
33287 },\r
33288 /**
33289 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
33290 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
33291 * if a height has not been set using CSS.
33292 * @return {Number}
33293 * @deprecated 5.0.0 use {@link Ext.dom.Element#getHeight} instead
33294 */\r
33295 getComputedHeight: function() {\r
33296 return Math.max(this.dom.offsetHeight, this.dom.clientHeight) || parseFloat(this.getStyle(HEIGHT)) || 0;\r
33297 },\r
33298 /**
33299 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
33300 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
33301 * if a width has not been set using CSS.
33302 * @return {Number}
33303 * @deprecated 5.0.0 use {@link Ext.dom.Element#getWidth} instead.
33304 */\r
33305 getComputedWidth: function() {\r
33306 return Math.max(this.dom.offsetWidth, this.dom.clientWidth) || parseFloat(this.getStyle(WIDTH)) || 0;\r
33307 },\r
33308 /**
33309 * Returns the dimensions of the element available to lay content out in.
33310 *
33311 * getStyleSize utilizes prefers style sizing if present, otherwise it chooses the larger of offsetHeight/clientHeight and
33312 * offsetWidth/clientWidth. To obtain the size excluding scrollbars, use getViewSize.
33313 *
33314 * Sizing of the document body is handled at the adapter level which handles special cases for IE and strict modes, etc.
33315 *
33316 * @return {Object} Object describing width and height.
33317 * @return {Number} return.width
33318 * @return {Number} return.height
33319 * @deprecated 5.0.0 Use {@link Ext.dom.Element#getSize} instead.
33320 */\r
33321 getStyleSize: function() {\r
33322 var me = this,\r
33323 d = this.dom,\r
33324 isDoc = (d === DOC || d === DOC.body),\r
33325 s, w, h;\r
33326 // If the body, use static methods\r
33327 if (isDoc) {\r
33328 return {\r
33329 width: Element.getViewportWidth(),\r
33330 height: Element.getViewportHeight()\r
33331 };\r
33332 }\r
33333 s = me.getStyle([\r
33334 'height',\r
33335 'width'\r
33336 ], true);\r
33337 //seek inline\r
33338 // Use Styles if they are set\r
33339 if (s.width && s.width !== 'auto') {\r
33340 w = parseFloat(s.width);\r
33341 }\r
33342 // Use Styles if they are set\r
33343 if (s.height && s.height !== 'auto') {\r
33344 h = parseFloat(s.height);\r
33345 }\r
33346 // Use getWidth/getHeight if style not set.\r
33347 return {\r
33348 width: w || me.getWidth(true),\r
33349 height: h || me.getHeight(true)\r
33350 };\r
33351 },\r
33352 /**
33353 * Returns true if this element uses the border-box-sizing model. This method is
33354 * deprecated as of version 5.0 because border-box sizing is forced upon all elements
33355 * via a style sheet rule, and the browsers that do not support border-box (IE6/7 strict
33356 * mode) are no longer supported.
33357 * @deprecated 5.0.0
33358 * @return {Boolean}
33359 */\r
33360 isBorderBox: function() {\r
33361 return true;\r
33362 },\r
33363 /**
33364 * Returns true if display is not "none"
33365 * @return {Boolean}
33366 * @deprecated 5.0.0 use element.isStyle('display', 'none');
33367 */\r
33368 isDisplayed: function() {\r
33369 return !this.isStyle('display', 'none');\r
33370 },\r
33371 /**
33372 * Checks whether this element can be focused.
33373 * @return {Boolean} True if the element is focusable
33374 * @deprecated 5.0.0 use {@link #isFocusable} instead
33375 */\r
33376 focusable: 'isFocusable'\r
33377 }\r
33378 }\r
33379 }\r
33380 };\r
33381})(), function() {\r
33382 var Element = Ext.dom.Element,\r
33383 proto = Element.prototype,\r
33384 useDocForId = !Ext.isIE8,\r
33385 DOC = document,\r
33386 view = DOC.defaultView,\r
33387 opacityRe = /alpha\(opacity=(.*)\)/i,\r
33388 trimRe = /^\s+|\s+$/g,\r
33389 styleHooks = proto.styleHooks,\r
33390 supports = Ext.supports,\r
33391 verticalStyleHooks90, verticalStyleHooks270, edges, k, edge, borderWidth, getBorderWidth;\r
33392 proto._init(Element);\r
33393 delete proto._init;\r
33394 Ext.plainTableCls = Ext.baseCSSPrefix + 'table-plain';\r
33395 Ext.plainListCls = Ext.baseCSSPrefix + 'list-plain';\r
33396 // ensure that any methods added by this override are also added to Ext.CompositeElementLite\r
33397 if (Ext.CompositeElementLite) {\r
33398 Ext.CompositeElementLite.importElementMethods();\r
33399 }\r
33400 if (!supports.Opacity && Ext.isIE) {\r
33401 Ext.apply(styleHooks.opacity, {\r
33402 get: function(dom) {\r
33403 var filter = dom.style.filter,\r
33404 match, opacity;\r
33405 if (filter.match) {\r
33406 match = filter.match(opacityRe);\r
33407 if (match) {\r
33408 opacity = parseFloat(match[1]);\r
33409 if (!isNaN(opacity)) {\r
33410 return opacity ? opacity / 100 : 0;\r
33411 }\r
33412 }\r
33413 }\r
33414 return 1;\r
33415 },\r
33416 set: function(dom, value) {\r
33417 var style = dom.style,\r
33418 val = style.filter.replace(opacityRe, '').replace(trimRe, '');\r
33419 style.zoom = 1;\r
33420 // ensure dom.hasLayout\r
33421 // value can be a number or '' or null... so treat falsey as no opacity\r
33422 if (typeof (value) === 'number' && value >= 0 && value < 1) {\r
33423 value *= 100;\r
33424 style.filter = val + (val.length ? ' ' : '') + 'alpha(opacity=' + value + ')';\r
33425 } else {\r
33426 style.filter = val;\r
33427 }\r
33428 }\r
33429 });\r
33430 }\r
33431 if (!supports.matchesSelector) {\r
33432 // Match basic tagName.ClassName selector syntax for is implementation\r
33433 var simpleSelectorRe = /^([a-z]+|\*)?(?:\.([a-z][a-z\-_0-9]*))?$/i,\r
33434 dashRe = /\-/g,\r
33435 fragment,\r
33436 classMatcher = function(tag, cls) {\r
33437 var classRe = new RegExp('(?:^|\\s+)' + cls.replace(dashRe, '\\-') + '(?:\\s+|$)');\r
33438 if (tag && tag !== '*') {\r
33439 tag = tag.toUpperCase();\r
33440 return function(el) {\r
33441 return el.tagName === tag && classRe.test(el.className);\r
33442 };\r
33443 }\r
33444 return function(el) {\r
33445 return classRe.test(el.className);\r
33446 };\r
33447 },\r
33448 tagMatcher = function(tag) {\r
33449 tag = tag.toUpperCase();\r
33450 return function(el) {\r
33451 return el.tagName === tag;\r
33452 };\r
33453 },\r
33454 cache = {};\r
33455 proto.matcherCache = cache;\r
33456 proto.is = function(selector) {\r
33457 // Empty selector always matches\r
33458 if (!selector) {\r
33459 return true;\r
33460 }\r
33461 var dom = this.dom,\r
33462 cls, match, testFn, root, isOrphan, is, tag;\r
33463 // Only Element node types can be matched.\r
33464 if (dom.nodeType !== 1) {\r
33465 return false;\r
33466 }\r
33467 if (!(testFn = Ext.isFunction(selector) ? selector : cache[selector])) {\r
33468 if (!(match = selector.match(simpleSelectorRe))) {\r
33469 // Not a simple tagName.className selector, do it the hard way\r
33470 root = dom.parentNode;\r
33471 if (!root) {\r
33472 isOrphan = true;\r
33473 root = fragment || (fragment = DOC.createDocumentFragment());\r
33474 fragment.appendChild(dom);\r
33475 }\r
33476 is = Ext.Array.indexOf(Ext.fly(root, '_is').query(selector), dom) !== -1;\r
33477 if (isOrphan) {\r
33478 fragment.removeChild(dom);\r
33479 }\r
33480 return is;\r
33481 }\r
33482 tag = match[1];\r
33483 cls = match[2];\r
33484 cache[selector] = testFn = cls ? classMatcher(tag, cls) : tagMatcher(tag);\r
33485 }\r
33486 return testFn(dom);\r
33487 };\r
33488 }\r
33489 // IE8 needs its own implementation of getStyle because it doesn't support getComputedStyle\r
33490 if (!view || !view.getComputedStyle) {\r
33491 proto.getStyle = function(property, inline) {\r
33492 var me = this,\r
33493 dom = me.dom,\r
33494 multiple = typeof property !== 'string',\r
33495 prop = property,\r
33496 props = prop,\r
33497 len = 1,\r
33498 isInline = inline,\r
33499 styleHooks = me.styleHooks,\r
33500 camel, domStyle, values, hook, out, style, i;\r
33501 if (multiple) {\r
33502 values = {};\r
33503 prop = props[0];\r
33504 i = 0;\r
33505 if (!(len = props.length)) {\r
33506 return values;\r
33507 }\r
33508 }\r
33509 if (!dom || dom.documentElement) {\r
33510 return values || '';\r
33511 }\r
33512 domStyle = dom.style;\r
33513 if (inline) {\r
33514 style = domStyle;\r
33515 } else {\r
33516 style = dom.currentStyle;\r
33517 // fallback to inline style if rendering context not available\r
33518 if (!style) {\r
33519 isInline = true;\r
33520 style = domStyle;\r
33521 }\r
33522 }\r
33523 do {\r
33524 hook = styleHooks[prop];\r
33525 if (!hook) {\r
33526 styleHooks[prop] = hook = {\r
33527 name: Element.normalize(prop)\r
33528 };\r
33529 }\r
33530 if (hook.get) {\r
33531 out = hook.get(dom, me, isInline, style);\r
33532 } else {\r
33533 camel = hook.name;\r
33534 out = style[camel];\r
33535 }\r
33536 if (!multiple) {\r
33537 return out;\r
33538 }\r
33539 values[prop] = out;\r
33540 prop = props[++i];\r
33541 } while (i < len);\r
33542 return values;\r
33543 };\r
33544 }\r
33545 // override getStyle for border-*-width\r
33546 if (Ext.isIE8) {\r
33547 getBorderWidth = function(dom, el, inline, style) {\r
33548 if (style[this.styleName] === 'none') {\r
33549 return '0px';\r
33550 }\r
33551 return style[this.name];\r
33552 };\r
33553 edges = [\r
33554 'Top',\r
33555 'Right',\r
33556 'Bottom',\r
33557 'Left'\r
33558 ];\r
33559 k = edges.length;\r
33560 while (k--) {\r
33561 edge = edges[k];\r
33562 borderWidth = 'border' + edge + 'Width';\r
33563 styleHooks['border-' + edge.toLowerCase() + '-width'] = styleHooks[borderWidth] = {\r
33564 name: borderWidth,\r
33565 styleName: 'border' + edge + 'Style',\r
33566 get: getBorderWidth\r
33567 };\r
33568 }\r
33569 // IE8 has an odd bug with handling font icons in pseudo elements;\r
33570 // it will render the icon once and not update it when something\r
33571 // like text color is changed via style addition or removal.\r
33572 // We have to force icon repaint by adding a style with forced empty\r
33573 // pseudo element content, (x-sync-repaint) and removing it back to work\r
33574 // around this issue.\r
33575 // See this: https://github.com/FortAwesome/Font-Awesome/issues/954\r
33576 // and this: https://github.com/twbs/bootstrap/issues/13863\r
33577 var syncRepaintCls = Ext.baseCSSPrefix + 'sync-repaint';\r
33578 proto.syncRepaint = function() {\r
33579 this.addCls(syncRepaintCls);\r
33580 // Measuring element width will make the browser to repaint it\r
33581 this.getWidth();\r
33582 // Removing empty content makes the icon to appear again and be redrawn\r
33583 this.removeCls(syncRepaintCls);\r
33584 };\r
33585 }\r
33586 if (Ext.isIE10m) {\r
33587 Ext.override(Element, {\r
33588 focus: function(defer, dom) {\r
33589 var me = this,\r
33590 ex;\r
33591 dom = dom || me.dom;\r
33592 if (Number(defer)) {\r
33593 Ext.defer(me.focus, defer, me, [\r
33594 null,\r
33595 dom\r
33596 ]);\r
33597 } else {\r
33598 Ext.GlobalEvents.fireEvent('beforefocus', dom);\r
33599 // IE10m has an acute problem with focusing input elements;\r
33600 // when the element was just shown and did not have enough\r
33601 // time to initialize, focusing it might fail. The problem\r
33602 // is somewhat random in nature; most of the time focusing\r
33603 // an input element will succeed, failing only occasionally.\r
33604 // When it fails, the focus will be thrown to the document\r
33605 // body element, with subsequent focusout/focusin event pair\r
33606 // on the body, which throws off our focusenter/focusleave\r
33607 // processing.\r
33608 // Fortunately for us, when this focus failure happens, the\r
33609 // resulting focusout event will happen *synchronously*\r
33610 // unlike the normal focusing events which IE will fire\r
33611 // asynchronously. Also fortunately for us, in most cases\r
33612 // trying to focus the given element the second time\r
33613 // immediately after it failed to focus the first time\r
33614 // seems to do the trick; however when second focus attempt\r
33615 // succeeds, it will result in focusout on the body and\r
33616 // focusin on the given element, which again wreaks havoc\r
33617 // on our focusenter/focusleave handling.\r
33618 // The only workable solution we have is to pretend that\r
33619 // focus never went to the document body and ignore the\r
33620 // focusout and focusin caused by failed first focus attempt.\r
33621 // To this end, we fudge the event stream in Focus publisher\r
33622 // override.\r
33623 if (dom && (dom.tagName === 'INPUT' || dom.tagname === 'TEXTAREA')) {\r
33624 Ext.synchronouslyFocusing = document.activeElement;\r
33625 }\r
33626 // Also note that trying to focus an unfocusable element\r
33627 // might throw an exception in IE8. What a cute idea, MS. :(\r
33628 try {\r
33629 dom.focus();\r
33630 } catch (xcpt) {\r
33631 ex = xcpt;\r
33632 }\r
33633 \r
33634 // Ok so now we have this situation when we tried to focus\r
33635 // the first time but did not succeed. Let's try again but\r
33636 // not if there was an exception the first time - when the\r
33637 // "focus failure" happens it does so silently. :(\r
33638 if (Ext.synchronouslyFocusing && document.activeElement !== dom && !ex) {\r
33639 dom.focus();\r
33640 }\r
33641 Ext.synchronouslyFocusing = null;\r
33642 }\r
33643 return me;\r
33644 }\r
33645 });\r
33646 }\r
33647 Ext.apply(Ext, {\r
33648 /**
33649 * `true` to automatically uncache orphaned Ext.Elements periodically. If set to
33650 * `false`, the application will be required to clean up orphaned Ext.Elements and
33651 * it's listeners as to not cause memory leakage.
33652 * @member Ext
33653 */\r
33654 enableGarbageCollector: true,\r
33655 // In sencha v5 isBorderBox is no longer needed since all supported browsers\r
33656 // support border-box, but it is hard coded to true for backward compatibility\r
33657 isBorderBox: true,\r
33658 /**
33659 * @property {Boolean} useShims
33660 * @member Ext
33661 * Set to `true` to use a {@link Ext.util.Floating#shim shim} on all floating Components
33662 * and {@link Ext.LoadMask LoadMasks}
33663 */\r
33664 useShims: false,\r
33665 /**
33666 * @private
33667 * Returns an HTML div element into which {@link Ext.container.Container#method-remove removed} components
33668 * are placed so that their DOM elements are not garbage collected as detached Dom trees.
33669 * @return {Ext.dom.Element}
33670 * @member Ext
33671 */\r
33672 getDetachedBody: function() {\r
33673 var detachedEl = Ext.detachedBodyEl;\r
33674 if (!detachedEl) {\r
33675 detachedEl = DOC.createElement('div');\r
33676 Ext.detachedBodyEl = detachedEl = new Ext.dom.Fly(detachedEl);\r
33677 detachedEl.isDetachedBody = true;\r
33678 }\r
33679 return detachedEl;\r
33680 },\r
33681 getElementById: function(id) {\r
33682 var el = DOC.getElementById(id),\r
33683 detachedBodyEl;\r
33684 if (!el && (detachedBodyEl = Ext.detachedBodyEl)) {\r
33685 el = detachedBodyEl.dom.querySelector(Ext.makeIdSelector(id));\r
33686 }\r
33687 return el;\r
33688 },\r
33689 /**
33690 * Applies event listeners to elements by selectors when the document is ready.
33691 * The event name is specified with an `@` suffix.
33692 *
33693 * Ext.addBehaviors({
33694 * // add a listener for click on all anchors in element with id foo
33695 * '#foo a@click': function(e, t){
33696 * // do something
33697 * },
33698 *
33699 * // add the same listener to multiple selectors (separated by comma BEFORE the @)
33700 * '#foo a, #bar span.some-class@mouseover': function(){
33701 * // do something
33702 * }
33703 * });
33704 *
33705 * @param {Object} obj The list of behaviors to apply
33706 * @member Ext
33707 */\r
33708 addBehaviors: function(o) {\r
33709 if (!Ext.isReady) {\r
33710 Ext.onInternalReady(function() {\r
33711 Ext.addBehaviors(o);\r
33712 });\r
33713 } else {\r
33714 var cache = {},\r
33715 // simple cache for applying multiple behaviors to same selector does query multiple times\r
33716 parts, b, s;\r
33717 for (b in o) {\r
33718 if ((parts = b.split('@'))[1]) {\r
33719 // for Object prototype breakers\r
33720 s = parts[0];\r
33721 if (!cache[s]) {\r
33722 cache[s] = Ext.fly(document).select(s, true);\r
33723 }\r
33724 cache[s].on(parts[1], o[b]);\r
33725 }\r
33726 }\r
33727 cache = null;\r
33728 }\r
33729 }\r
33730 });\r
33731 if (Ext.isIE9m) {\r
33732 Ext.getElementById = function(id) {\r
33733 var el = DOC.getElementById(id),\r
33734 detachedBodyEl;\r
33735 if (!el && (detachedBodyEl = Ext.detachedBodyEl)) {\r
33736 el = detachedBodyEl.dom.all[id];\r
33737 }\r
33738 return el;\r
33739 };\r
33740 proto.getById = function(id, asDom) {\r
33741 var dom = this.dom,\r
33742 ret = null,\r
33743 entry, el;\r
33744 if (dom) {\r
33745 // for normal elements getElementById is the best solution, but if the el is\r
33746 // not part of the document.body, we need to use all[]\r
33747 el = (useDocForId && DOC.getElementById(id)) || dom.all[id];\r
33748 if (el) {\r
33749 if (asDom) {\r
33750 ret = el;\r
33751 } else {\r
33752 // calling Element.get here is a real hit (2x slower) because it has to\r
33753 // redetermine that we are giving it a dom el.\r
33754 entry = Ext.cache[id];\r
33755 if (entry) {\r
33756 if (entry.skipGarbageCollection || !Ext.isGarbage(entry.dom)) {\r
33757 ret = entry;\r
33758 } else {\r
33759 Ext.raise("Stale Element with id '" + el.id + "' found in Element cache. " + "Make sure to clean up Element instances using destroy()");\r
33760 entry.destroy();\r
33761 }\r
33762 }\r
33763 ret = ret || new Ext.Element(el);\r
33764 }\r
33765 }\r
33766 }\r
33767 return ret;\r
33768 };\r
33769 } else if (!DOC.querySelector) {\r
33770 Ext.getDetachedBody = Ext.getBody;\r
33771 Ext.getElementById = function(id) {\r
33772 return DOC.getElementById(id);\r
33773 };\r
33774 proto.getById = function(id, asDom) {\r
33775 var dom = DOC.getElementById(id);\r
33776 return asDom ? dom : (dom ? Ext.get(dom) : null);\r
33777 };\r
33778 }\r
33779 if (Ext.isIE && !(Ext.isIE9p && DOC.documentMode >= 9)) {\r
33780 // Essentially all web browsers (Firefox, Internet Explorer, recent versions of Opera, Safari, Konqueror, and iCab,\r
33781 // as a non-exhaustive list) return null when the specified attribute does not exist on the specified element.\r
33782 // The DOM specification says that the correct return value in this case is actually the empty string, and some\r
33783 // DOM implementations implement this behavior. The implementation of getAttribute in XUL (Gecko) actually follows\r
33784 // the specification and returns an empty string. Consequently, you should use hasAttribute to check for an attribute's\r
33785 // existence prior to calling getAttribute() if it is possible that the requested attribute does not exist on the specified element.\r
33786 //\r
33787 // https://developer.mozilla.org/en-US/docs/DOM/element.getAttribute\r
33788 // http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-745549614\r
33789 proto.getAttribute = function(name, ns) {\r
33790 var d = this.dom,\r
33791 type;\r
33792 if (ns) {\r
33793 type = typeof d[ns + ":" + name];\r
33794 if (type !== 'undefined' && type !== 'unknown') {\r
33795 return d[ns + ":" + name] || null;\r
33796 }\r
33797 return null;\r
33798 }\r
33799 if (name === "for") {\r
33800 name = "htmlFor";\r
33801 }\r
33802 return d[name] || null;\r
33803 };\r
33804 }\r
33805 Ext.onInternalReady(function() {\r
33806 var transparentRe = /^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i,\r
33807 bodyCls = [],\r
33808 //htmlCls = [],\r
33809 origSetWidth = proto.setWidth,\r
33810 origSetHeight = proto.setHeight,\r
33811 origSetSize = proto.setSize,\r
33812 pxRe = /^\d+(?:\.\d*)?px$/i,\r
33813 colorStyles, i, name, camel;\r
33814 if (supports.FixedTableWidthBug) {\r
33815 // EXTJSIV-12665\r
33816 // https://bugs.webkit.org/show_bug.cgi?id=130239\r
33817 // Webkit browsers fail to layout correctly when a form field's width is less\r
33818 // than the min-width of the body element. The only way to fix it seems to be\r
33819 // to toggle the display style of the field's element before and after setting\r
33820 // the width. Note: once the bug has been corrected by toggling the element's\r
33821 // display, successive calls to setWidth will work without the hack. It's only\r
33822 // when going from naturally widthed to having an explicit width that the bug\r
33823 // occurs.\r
33824 styleHooks.width = {\r
33825 name: 'width',\r
33826 set: function(dom, value, el) {\r
33827 var style = dom.style,\r
33828 needsFix = el._needsTableWidthFix,\r
33829 origDisplay = style.display;\r
33830 if (needsFix) {\r
33831 style.display = 'none';\r
33832 }\r
33833 style.width = value;\r
33834 if (needsFix) {\r
33835 // repaint\r
33836 dom.scrollWidth;\r
33837 // jshint ignore:line\r
33838 style.display = origDisplay;\r
33839 }\r
33840 }\r
33841 };\r
33842 proto.setWidth = function(width, animate) {\r
33843 var me = this,\r
33844 dom = me.dom,\r
33845 style = dom.style,\r
33846 needsFix = me._needsTableWidthFix,\r
33847 origDisplay = style.display;\r
33848 if (needsFix && !animate) {\r
33849 style.display = 'none';\r
33850 }\r
33851 origSetWidth.call(me, width, animate);\r
33852 if (needsFix && !animate) {\r
33853 // repaint\r
33854 dom.scrollWidth;\r
33855 // jshint ignore:line\r
33856 style.display = origDisplay;\r
33857 }\r
33858 return me;\r
33859 };\r
33860 proto.setSize = function(width, height, animate) {\r
33861 var me = this,\r
33862 dom = me.dom,\r
33863 style = dom.style,\r
33864 needsFix = me._needsTableWidthFix,\r
33865 origDisplay = style.display;\r
33866 if (needsFix && !animate) {\r
33867 style.display = 'none';\r
33868 }\r
33869 origSetSize.call(me, width, height, animate);\r
33870 if (needsFix && !animate) {\r
33871 // repaint\r
33872 dom.scrollWidth;\r
33873 // jshint ignore:line\r
33874 style.display = origDisplay;\r
33875 }\r
33876 return me;\r
33877 };\r
33878 }\r
33879 if (Ext.isIE8) {\r
33880 styleHooks.height = {\r
33881 name: 'height',\r
33882 set: function(dom, value, el) {\r
33883 var component = el.component,\r
33884 frameInfo, frameBodyStyle;\r
33885 if (component && component._syncFrameHeight && el === component.el) {\r
33886 frameBodyStyle = component.frameBody.dom.style;\r
33887 if (pxRe.test(value)) {\r
33888 frameInfo = component.getFrameInfo();\r
33889 if (frameInfo) {\r
33890 frameBodyStyle.height = (parseInt(value, 10) - frameInfo.height) + 'px';\r
33891 }\r
33892 } else if (!value || value === 'auto') {\r
33893 frameBodyStyle.height = '';\r
33894 }\r
33895 }\r
33896 dom.style.height = value;\r
33897 }\r
33898 };\r
33899 proto.setHeight = function(height, animate) {\r
33900 var component = this.component,\r
33901 frameInfo, frameBodyStyle;\r
33902 if (component && component._syncFrameHeight && this === component.el) {\r
33903 frameBodyStyle = component.frameBody.dom.style;\r
33904 if (!height || height === 'auto') {\r
33905 frameBodyStyle.height = '';\r
33906 } else {\r
33907 frameInfo = component.getFrameInfo();\r
33908 if (frameInfo) {\r
33909 frameBodyStyle.height = (height - frameInfo.height) + 'px';\r
33910 }\r
33911 }\r
33912 }\r
33913 return origSetHeight.call(this, height, animate);\r
33914 };\r
33915 proto.setSize = function(width, height, animate) {\r
33916 var component = this.component,\r
33917 frameInfo, frameBodyStyle;\r
33918 if (component && component._syncFrameHeight && this === component.el) {\r
33919 frameBodyStyle = component.frameBody.dom.style;\r
33920 if (!height || height === 'auto') {\r
33921 frameBodyStyle.height = '';\r
33922 } else {\r
33923 frameInfo = component.getFrameInfo();\r
33924 if (frameInfo) {\r
33925 frameBodyStyle.height = (height - frameInfo.height) + 'px';\r
33926 }\r
33927 }\r
33928 }\r
33929 return origSetSize.call(this, width, height, animate);\r
33930 };\r
33931 }\r
33932 // Element.unselectable relies on this listener to prevent selection in IE. Some other browsers support the event too\r
33933 // but it is only strictly required for IE. In WebKit this listener causes subtle differences to how the browser handles\r
33934 // the non-selection, e.g. whether or not the mouse cursor changes when attempting to select text.\r
33935 Ext.getDoc().on('selectstart', function(ev, dom) {\r
33936 var selectableCls = Element.selectableCls,\r
33937 unselectableCls = Element.unselectableCls,\r
33938 tagName = dom && dom.tagName;\r
33939 tagName = tagName && tagName.toLowerCase();\r
33940 // Element.unselectable is not really intended to handle selection within text fields and it is important that\r
33941 // fields inside menus or panel headers don't inherit the unselectability. In most browsers this is automatic but in\r
33942 // IE 9 the selectstart event can bubble up from text fields so we have to explicitly handle that case.\r
33943 if (tagName === 'input' || tagName === 'textarea') {\r
33944 return;\r
33945 }\r
33946 // Walk up the DOM checking the nodes. This may be 'slow' but selectstart events don't fire very often\r
33947 while (dom && dom.nodeType === 1 && dom !== DOC.documentElement) {\r
33948 var el = Ext.fly(dom);\r
33949 // If the node has the class x-selectable then stop looking, the text selection is allowed\r
33950 if (el.hasCls(selectableCls)) {\r
33951 return;\r
33952 }\r
33953 // If the node has class x-unselectable then the text selection needs to be stopped\r
33954 if (el.hasCls(unselectableCls)) {\r
33955 ev.stopEvent();\r
33956 return;\r
33957 }\r
33958 dom = dom.parentNode;\r
33959 }\r
33960 });\r
33961 function fixTransparent(dom, el, inline, style) {\r
33962 var value = style[this.name] || '';\r
33963 return transparentRe.test(value) ? 'transparent' : value;\r
33964 }\r
33965 /*
33966 * Helper function to create the function that will restore the selection.
33967 */\r
33968 function makeSelectionRestoreFn(activeEl, start, end) {\r
33969 return function() {\r
33970 activeEl.selectionStart = start;\r
33971 activeEl.selectionEnd = end;\r
33972 };\r
33973 }\r
33974 /**
33975 * Creates a function to call to clean up problems with the work-around for the
33976 * WebKit RightMargin bug. The work-around is to add "display: 'inline-block'" to
33977 * the element before calling getComputedStyle and then to restore its original
33978 * display value. The problem with this is that it corrupts the selection of an
33979 * INPUT or TEXTAREA element (as in the "I-beam" goes away but the focus remains).
33980 * To cleanup after this, we need to capture the selection of any such element and
33981 * then restore it after we have restored the display style.
33982 *
33983 * @param {HTMLElement} target The top-most element being adjusted.
33984 * @private
33985 */\r
33986 function getRightMarginFixCleaner(target) {\r
33987 var hasInputBug = supports.DisplayChangeInputSelectionBug,\r
33988 hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug,\r
33989 activeEl, tag, start, end;\r
33990 if (hasInputBug || hasTextAreaBug) {\r
33991 activeEl = Element.getActiveElement();\r
33992 tag = activeEl && activeEl.tagName;\r
33993 if ((hasTextAreaBug && tag === 'TEXTAREA') || (hasInputBug && tag === 'INPUT' && activeEl.type === 'text')) {\r
33994 if (Ext.fly(target).isAncestor(activeEl)) {\r
33995 start = activeEl.selectionStart;\r
33996 end = activeEl.selectionEnd;\r
33997 if (Ext.isNumber(start) && Ext.isNumber(end)) {\r
33998 // to be safe...\r
33999 // We don't create the raw closure here inline because that\r
34000 // will be costly even if we don't want to return it (nested\r
34001 // function decls and exprs are often instantiated on entry\r
34002 // regardless of whether execution ever reaches them):\r
34003 return makeSelectionRestoreFn(activeEl, start, end);\r
34004 }\r
34005 }\r
34006 }\r
34007 }\r
34008 return Ext.emptyFn;\r
34009 }\r
34010 // avoid special cases, just return a nop\r
34011 function fixRightMargin(dom, el, inline, style) {\r
34012 var result = style.marginRight,\r
34013 domStyle, display;\r
34014 // Ignore cases when the margin is correctly reported as 0, the bug only shows\r
34015 // numbers larger.\r
34016 if (result !== '0px') {\r
34017 domStyle = dom.style;\r
34018 display = domStyle.display;\r
34019 domStyle.display = 'inline-block';\r
34020 result = (inline ? style : dom.ownerDocument.defaultView.getComputedStyle(dom, null)).marginRight;\r
34021 domStyle.display = display;\r
34022 }\r
34023 return result;\r
34024 }\r
34025 function fixRightMarginAndInputFocus(dom, el, inline, style) {\r
34026 var result = style.marginRight,\r
34027 domStyle, cleaner, display;\r
34028 if (result !== '0px') {\r
34029 domStyle = dom.style;\r
34030 cleaner = getRightMarginFixCleaner(dom);\r
34031 display = domStyle.display;\r
34032 domStyle.display = 'inline-block';\r
34033 result = (inline ? style : dom.ownerDocument.defaultView.getComputedStyle(dom, '')).marginRight;\r
34034 domStyle.display = display;\r
34035 cleaner();\r
34036 }\r
34037 return result;\r
34038 }\r
34039 // Fix bug caused by this: https://bugs.webkit.org/show_bug.cgi?id=13343\r
34040 if (!supports.RightMargin) {\r
34041 styleHooks.marginRight = styleHooks['margin-right'] = {\r
34042 name: 'marginRight',\r
34043 // TODO - Touch should use conditional compilation here or ensure that the\r
34044 // underlying Ext.supports flags are set correctly...\r
34045 get: (supports.DisplayChangeInputSelectionBug || supports.DisplayChangeTextAreaSelectionBug) ? fixRightMarginAndInputFocus : fixRightMargin\r
34046 };\r
34047 }\r
34048 if (!supports.TransparentColor) {\r
34049 colorStyles = [\r
34050 'background-color',\r
34051 'border-color',\r
34052 'color',\r
34053 'outline-color'\r
34054 ];\r
34055 for (i = colorStyles.length; i--; ) {\r
34056 name = colorStyles[i];\r
34057 camel = Element.normalize(name);\r
34058 styleHooks[name] = styleHooks[camel] = {\r
34059 name: camel,\r
34060 get: fixTransparent\r
34061 };\r
34062 }\r
34063 }\r
34064 // When elements are rotated 80 or 270 degrees, their border, margin and padding hooks\r
34065 // need to be rotated as well.\r
34066 proto.verticalStyleHooks90 = verticalStyleHooks90 = Ext.Object.chain(styleHooks);\r
34067 proto.verticalStyleHooks270 = verticalStyleHooks270 = Ext.Object.chain(styleHooks);\r
34068 verticalStyleHooks90.width = styleHooks.height || {\r
34069 name: 'height'\r
34070 };\r
34071 verticalStyleHooks90.height = styleHooks.width || {\r
34072 name: 'width'\r
34073 };\r
34074 verticalStyleHooks90['margin-top'] = {\r
34075 name: 'marginLeft'\r
34076 };\r
34077 verticalStyleHooks90['margin-right'] = {\r
34078 name: 'marginTop'\r
34079 };\r
34080 verticalStyleHooks90['margin-bottom'] = {\r
34081 name: 'marginRight'\r
34082 };\r
34083 verticalStyleHooks90['margin-left'] = {\r
34084 name: 'marginBottom'\r
34085 };\r
34086 verticalStyleHooks90['padding-top'] = {\r
34087 name: 'paddingLeft'\r
34088 };\r
34089 verticalStyleHooks90['padding-right'] = {\r
34090 name: 'paddingTop'\r
34091 };\r
34092 verticalStyleHooks90['padding-bottom'] = {\r
34093 name: 'paddingRight'\r
34094 };\r
34095 verticalStyleHooks90['padding-left'] = {\r
34096 name: 'paddingBottom'\r
34097 };\r
34098 verticalStyleHooks90['border-top'] = {\r
34099 name: 'borderLeft'\r
34100 };\r
34101 verticalStyleHooks90['border-right'] = {\r
34102 name: 'borderTop'\r
34103 };\r
34104 verticalStyleHooks90['border-bottom'] = {\r
34105 name: 'borderRight'\r
34106 };\r
34107 verticalStyleHooks90['border-left'] = {\r
34108 name: 'borderBottom'\r
34109 };\r
34110 verticalStyleHooks270.width = styleHooks.height || {\r
34111 name: 'height'\r
34112 };\r
34113 verticalStyleHooks270.height = styleHooks.width || {\r
34114 name: 'width'\r
34115 };\r
34116 verticalStyleHooks270['margin-top'] = {\r
34117 name: 'marginRight'\r
34118 };\r
34119 verticalStyleHooks270['margin-right'] = {\r
34120 name: 'marginBottom'\r
34121 };\r
34122 verticalStyleHooks270['margin-bottom'] = {\r
34123 name: 'marginLeft'\r
34124 };\r
34125 verticalStyleHooks270['margin-left'] = {\r
34126 name: 'marginTop'\r
34127 };\r
34128 verticalStyleHooks270['padding-top'] = {\r
34129 name: 'paddingRight'\r
34130 };\r
34131 verticalStyleHooks270['padding-right'] = {\r
34132 name: 'paddingBottom'\r
34133 };\r
34134 verticalStyleHooks270['padding-bottom'] = {\r
34135 name: 'paddingLeft'\r
34136 };\r
34137 verticalStyleHooks270['padding-left'] = {\r
34138 name: 'paddingTop'\r
34139 };\r
34140 verticalStyleHooks270['border-top'] = {\r
34141 name: 'borderRight'\r
34142 };\r
34143 verticalStyleHooks270['border-right'] = {\r
34144 name: 'borderBottom'\r
34145 };\r
34146 verticalStyleHooks270['border-bottom'] = {\r
34147 name: 'borderLeft'\r
34148 };\r
34149 verticalStyleHooks270['border-left'] = {\r
34150 name: 'borderTop'\r
34151 };\r
34152 /**
34153 * @property {Boolean} scopeCss
34154 * @member Ext
34155 * Set this to true before onReady to prevent any styling from being added to
34156 * the body element. By default a few styles such as font-family, and color
34157 * are added to the body element via a "x-body" class. When this is set to
34158 * `true` the "x-body" class is not added to the body element, but is added
34159 * to the elements of root-level containers instead.
34160 */\r
34161 if (!Ext.scopeCss) {\r
34162 bodyCls.push(Ext.baseCSSPrefix + 'body');\r
34163 }\r
34164 if (supports.Touch) {\r
34165 bodyCls.push(Ext.baseCSSPrefix + 'touch');\r
34166 }\r
34167 if (Ext.isIE && Ext.isIE9m) {\r
34168 bodyCls.push(Ext.baseCSSPrefix + 'ie', Ext.baseCSSPrefix + 'ie9m');\r
34169 // very often CSS needs to do checks like "IE7+" or "IE6 or 7". To help\r
34170 // reduce the clutter (since CSS/SCSS cannot do these tests), we add some\r
34171 // additional classes:\r
34172 //\r
34173 // x-ie7p : IE7+ : 7 <= ieVer\r
34174 // x-ie7m : IE7- : ieVer <= 7\r
34175 // x-ie8p : IE8+ : 8 <= ieVer\r
34176 // x-ie8m : IE8- : ieVer <= 8\r
34177 // x-ie9p : IE9+ : 9 <= ieVer\r
34178 // x-ie78 : IE7 or 8 : 7 <= ieVer <= 8\r
34179 //\r
34180 bodyCls.push(Ext.baseCSSPrefix + 'ie8p');\r
34181 if (Ext.isIE8) {\r
34182 bodyCls.push(Ext.baseCSSPrefix + 'ie8');\r
34183 } else {\r
34184 bodyCls.push(Ext.baseCSSPrefix + 'ie9', Ext.baseCSSPrefix + 'ie9p');\r
34185 }\r
34186 if (Ext.isIE8m) {\r
34187 bodyCls.push(Ext.baseCSSPrefix + 'ie8m');\r
34188 }\r
34189 }\r
34190 if (Ext.isIE10) {\r
34191 bodyCls.push(Ext.baseCSSPrefix + 'ie10');\r
34192 }\r
34193 if (Ext.isIE10p) {\r
34194 bodyCls.push(Ext.baseCSSPrefix + 'ie10p');\r
34195 }\r
34196 if (Ext.isIE11) {\r
34197 bodyCls.push(Ext.baseCSSPrefix + 'ie11');\r
34198 }\r
34199 if (Ext.isGecko) {\r
34200 bodyCls.push(Ext.baseCSSPrefix + 'gecko');\r
34201 }\r
34202 if (Ext.isOpera) {\r
34203 bodyCls.push(Ext.baseCSSPrefix + 'opera');\r
34204 }\r
34205 if (Ext.isOpera12m) {\r
34206 bodyCls.push(Ext.baseCSSPrefix + 'opera12m');\r
34207 }\r
34208 if (Ext.isWebKit) {\r
34209 bodyCls.push(Ext.baseCSSPrefix + 'webkit');\r
34210 }\r
34211 if (Ext.isSafari) {\r
34212 bodyCls.push(Ext.baseCSSPrefix + 'safari');\r
34213 }\r
34214 if (Ext.isChrome) {\r
34215 bodyCls.push(Ext.baseCSSPrefix + 'chrome');\r
34216 }\r
34217 if (Ext.isMac) {\r
34218 bodyCls.push(Ext.baseCSSPrefix + 'mac');\r
34219 }\r
34220 if (Ext.isLinux) {\r
34221 bodyCls.push(Ext.baseCSSPrefix + 'linux');\r
34222 }\r
34223 if (!supports.CSS3BorderRadius) {\r
34224 bodyCls.push(Ext.baseCSSPrefix + 'nbr');\r
34225 }\r
34226 if (!supports.CSS3LinearGradient) {\r
34227 bodyCls.push(Ext.baseCSSPrefix + 'nlg');\r
34228 }\r
34229 if (supports.Touch) {\r
34230 bodyCls.push(Ext.baseCSSPrefix + 'touch');\r
34231 }\r
34232 //Ext.fly(document.documentElement).addCls(htmlCls);\r
34233 Ext.getBody().addCls(bodyCls);\r
34234 }, null, {\r
34235 priority: 1500\r
34236 });\r
34237});\r
34238// onReady\r
34239\r
34240// @tag core\r
34241/**
34242 * @class Ext.GlobalEvents
34243 */\r
34244Ext.define('Ext.overrides.GlobalEvents', {\r
34245 override: 'Ext.GlobalEvents',\r
34246 /**
34247 * @event resumelayouts
34248 * Fires after global layout processing has been resumed in {@link
34249 * Ext.Component#resumeLayouts}.
34250 */\r
34251 deprecated: {\r
34252 5: {\r
34253 methods: {\r
34254 addListener: function(ename, fn, scope, options, order, caller, eventOptions) {\r
34255 var name, readyFn;\r
34256 // The "ready" event was removed from Ext.globalEvents in 5.0 in favor of\r
34257 // Ext.onReady(). This function adds compatibility for the ready event\r
34258 if (ename === 'ready') {\r
34259 readyFn = fn;\r
34260 } else if (typeof ename !== 'string') {\r
34261 for (name in ename) {\r
34262 if (name === 'ready') {\r
34263 readyFn = ename[name];\r
34264 }\r
34265 }\r
34266 }\r
34267 if (readyFn) {\r
34268 Ext.log.warn("Ext.on('ready', fn) is deprecated. Please use Ext.onReady(fn) instead.");\r
34269 Ext.onReady(readyFn);\r
34270 }\r
34271 this.callParent([\r
34272 ename,\r
34273 fn,\r
34274 scope,\r
34275 options,\r
34276 order,\r
34277 caller,\r
34278 eventOptions\r
34279 ]);\r
34280 }\r
34281 }\r
34282 }\r
34283 }\r
34284});\r
34285\r
34286/**
34287 *
34288 */\r
34289Ext.define('Ext.overrides.Widget', {\r
34290 override: 'Ext.Widget',\r
34291 uses: [\r
34292 'Ext.Component'\r
34293 ],\r
34294 $configStrict: false,\r
34295 isComponent: true,\r
34296 liquidLayout: true,\r
34297 // in Ext JS the rendered flag is set as soon as a component has its element. Since\r
34298 // widgets always have an element when constructed, they are always considered to be\r
34299 // "rendered"\r
34300 rendered: true,\r
34301 rendering: true,\r
34302 config: {\r
34303 renderTo: null\r
34304 },\r
34305 cachedConfig: {\r
34306 baseCls: Ext.baseCSSPrefix + 'widget'\r
34307 },\r
34308 constructor: function(config) {\r
34309 var me = this,\r
34310 renderTo;\r
34311 me.callParent([\r
34312 config\r
34313 ]);\r
34314 // initialize the component layout\r
34315 me.getComponentLayout();\r
34316 renderTo = me.getRenderTo();\r
34317 if (renderTo) {\r
34318 me.render(renderTo);\r
34319 }\r
34320 },\r
34321 addClsWithUI: function(cls) {\r
34322 this.el.addCls(cls);\r
34323 },\r
34324 afterComponentLayout: Ext.emptyFn,\r
34325 updateLayout: function() {\r
34326 var owner = this.getRefOwner();\r
34327 if (owner) {\r
34328 owner.updateLayout();\r
34329 }\r
34330 },\r
34331 destroy: function() {\r
34332 var me = this,\r
34333 ownerCt = me.ownerCt;\r
34334 if (ownerCt && ownerCt.remove) {\r
34335 ownerCt.remove(me, false);\r
34336 }\r
34337 me.callParent();\r
34338 },\r
34339 finishRender: function() {\r
34340 this.rendering = false;\r
34341 this.initBindable();\r
34342 },\r
34343 getAnimationProps: function() {\r
34344 // see Ext.util.Animate mixin\r
34345 return {};\r
34346 },\r
34347 getComponentLayout: function() {\r
34348 var me = this,\r
34349 layout = me.componentLayout;\r
34350 if (!layout) {\r
34351 layout = me.componentLayout = new Ext.layout.component.Auto();\r
34352 layout.setOwner(me);\r
34353 }\r
34354 return layout;\r
34355 },\r
34356 getEl: function() {\r
34357 return this.element;\r
34358 },\r
34359 /**
34360 * @private
34361 * Needed for when widget is rendered into a grid cell. The class to add to the cell element.
34362 * @member Ext.Widget
34363 */\r
34364 getTdCls: function() {\r
34365 return Ext.baseCSSPrefix + this.getTdType() + '-' + (this.ui || 'default') + '-cell';\r
34366 },\r
34367 /**
34368 * @private
34369 * Partner method to {@link #getTdCls}.
34370 *
34371 * Returns the base type for the component. Defaults to return `this.xtype`, but
34372 * All derived classes of {@link Ext.form.field.Text TextField} can return the type 'textfield',
34373 * and all derived classes of {@link Ext.button.Button Button} can return the type 'button'
34374 * @member Ext.Widget
34375 */\r
34376 getTdType: function() {\r
34377 return this.xtype;\r
34378 },\r
34379 getItemId: function() {\r
34380 // needed by ComponentQuery\r
34381 return this.itemId || this.id;\r
34382 },\r
34383 getSizeModel: function() {\r
34384 return Ext.Component.prototype.getSizeModel.apply(this, arguments);\r
34385 },\r
34386 onAdded: function(container, pos, instanced) {\r
34387 var me = this,\r
34388 inheritedState = me.inheritedState;\r
34389 me.ownerCt = container;\r
34390 me.onInheritedAdd(me, instanced);\r
34391 },\r
34392 onRemoved: function(destroying) {\r
34393 var me = this;\r
34394 if (!destroying) {\r
34395 me.removeBindings();\r
34396 }\r
34397 me.onInheritedRemove(destroying);\r
34398 me.ownerCt = me.ownerLayout = null;\r
34399 },\r
34400 parseBox: function(box) {\r
34401 return Ext.Element.parseBox(box);\r
34402 },\r
34403 removeClsWithUI: function(cls) {\r
34404 this.el.removeCls(cls);\r
34405 },\r
34406 render: function(container, position) {\r
34407 var me = this,\r
34408 element = me.element,\r
34409 proto = Ext.Component.prototype,\r
34410 nextSibling;\r
34411 if (!me.ownerCt || me.floating) {\r
34412 if (Ext.scopeCss) {\r
34413 element.addCls(proto.rootCls);\r
34414 }\r
34415 element.addCls(proto.borderBoxCls);\r
34416 }\r
34417 if (position) {\r
34418 nextSibling = container.childNodes[position];\r
34419 if (nextSibling) {\r
34420 Ext.fly(container).insertBefore(element, nextSibling);\r
34421 return;\r
34422 }\r
34423 }\r
34424 Ext.fly(container).appendChild(element);\r
34425 },\r
34426 setPosition: function(x, y) {\r
34427 this.el.setLocalXY(x, y);\r
34428 },\r
34429 up: function() {\r
34430 return Ext.Component.prototype.up.apply(this, arguments);\r
34431 },\r
34432 isAncestor: function() {\r
34433 return Ext.Component.prototype.isAncestor.apply(this, arguments);\r
34434 },\r
34435 onFocusEnter: function() {\r
34436 return Ext.Component.prototype.onFocusEnter.apply(this, arguments);\r
34437 },\r
34438 onFocusLeave: function() {\r
34439 return Ext.Component.prototype.onFocusLeave.apply(this, arguments);\r
34440 },\r
34441 isLayoutChild: function(candidate) {\r
34442 var ownerCt = this.ownerCt;\r
34443 return ownerCt ? (ownerCt === candidate || ownerCt.isLayoutChild(candidate)) : false;\r
34444 }\r
34445}, function(Cls) {\r
34446 var prototype = Cls.prototype;\r
34447 if (Ext.isIE9m) {\r
34448 // Since IE8/9 don't not support Object.defineProperty correctly we can't add the reference\r
34449 // nodes on demand, so we just fall back to adding all references up front.\r
34450 prototype.addElementReferenceOnDemand = prototype.addElementReference;\r
34451 }\r
34452});\r
34453\r
34454Ext.define('Ext.overrides.Progress', {\r
34455 override: 'Ext.Progress',\r
34456 config: {\r
34457 ui: 'default'\r
34458 }\r
34459});\r
34460\r
34461Ext.define('Ext.overrides.app.domain.Component', {\r
34462 override: 'Ext.app.domain.Component',\r
34463 requires: [\r
34464 'Ext.Component'\r
34465 ]\r
34466}, function(ComponentDomain) {\r
34467 // The core Component domain monitors events on the Ext.Widget class\r
34468 // in Ext Components are not widgets so we need to monitor Ext.Component as well.\r
34469 ComponentDomain.monitor(Ext.Component);\r
34470});\r
34471\r
34472// This is an override because it must be loaded very early, possibly before Ext.app.Application\r
34473// in dev mode so that Ext.application() can be called.\r
34474// Being an override also ensures that it is only included in a built app if Ext.app.Application\r
34475// is present.\r
34476//\r
34477// @override Ext.app.Application\r
34478/**
34479 * @method application
34480 * @member Ext
34481 * Loads Ext.app.Application class and starts it up with given configuration after the
34482 * page is ready.
34483 *
34484 * See `Ext.app.Application` for details.
34485 *
34486 * @param {Object/String} config Application config object or name of a class derived
34487 * from Ext.app.Application.
34488 */\r
34489Ext.application = function(config) {\r
34490 var createApp = function(App) {\r
34491 // This won't be called until App class has been created.\r
34492 Ext.onReady(function() {\r
34493 var Viewport = Ext.viewport;\r
34494 Viewport = Viewport && Viewport['Viewport'];\r
34495 if (Viewport && Viewport.setup) {\r
34496 Viewport.setup(App.prototype.config.viewport);\r
34497 }\r
34498 Ext.app.Application.instance = new App();\r
34499 });\r
34500 };\r
34501 if (typeof config === "string") {\r
34502 Ext.require(config, function() {\r
34503 createApp(Ext.ClassManager.get(config));\r
34504 });\r
34505 } else {\r
34506 config = Ext.apply({\r
34507 extend: 'Ext.app.Application'\r
34508 }, // can be replaced by config!\r
34509 config);\r
34510 // We have to process "paths" before creating Application class,\r
34511 // or `requires` won't work.\r
34512 Ext.app.setupPaths(config.name, config.appFolder, config.paths);\r
34513 config['paths processed'] = true;\r
34514 // Let Ext.define do the hard work but don't assign a class name.\r
34515 Ext.define(config.name + ".$application", config, function() {\r
34516 createApp(this);\r
34517 });\r
34518 }\r
34519};\r
34520\r
34521/**
34522 *
34523 */\r
34524Ext.define('Ext.overrides.app.Application', {\r
34525 override: 'Ext.app.Application',\r
34526 uses: [\r
34527 'Ext.tip.QuickTipManager'\r
34528 ],\r
34529 // @cmd-auto-dependency {aliasPrefix: "view.", mvc: true, requires: ["Ext.plugin.Viewport"]}\r
34530 /**
34531 * @cfg {Boolean/String} [autoCreateViewport=false]
34532 * @deprecated 5.1 Instead use {@link #mainView}
34533 * @member Ext.app.Application
34534 */\r
34535 autoCreateViewport: false,\r
34536 config: {\r
34537 /**
34538 * @cfg {Boolean} enableQuickTips
34539 * True to automatically set up Ext.tip.QuickTip support.
34540 * @member Ext.app.Application
34541 */\r
34542 enableQuickTips: true\r
34543 },\r
34544 applyMainView: function(mainView) {\r
34545 var view, proto, config, plugins;\r
34546 if (typeof mainView === 'string') {\r
34547 view = this.getView(mainView);\r
34548 } else {\r
34549 view = Ext.ClassManager.getByConfig(mainView);\r
34550 }\r
34551 proto = view.prototype;\r
34552 if (!proto.isViewport) {\r
34553 plugins = proto.plugins;\r
34554 // Need to copy over any plugins defined on the prototype.\r
34555 plugins = [\r
34556 'viewport'\r
34557 ].concat(plugins ? Ext.Array.from(plugins, true) : []);\r
34558 config = {\r
34559 plugins: plugins\r
34560 };\r
34561 }\r
34562 return view.create(config);\r
34563 },\r
34564 getDependencies: function(cls, data, requires) {\r
34565 var Controller = Ext.app.Controller,\r
34566 proto = cls.prototype,\r
34567 namespace = data.$namespace,\r
34568 viewportClass = data.autoCreateViewport;\r
34569 if (viewportClass) {\r
34570 if (!namespace) {\r
34571 Ext.raise("[Ext.app.Application] Can't resolve namespace for " + data.$className + ", did you forget to specify 'name' property?");\r
34572 }\r
34573 if (viewportClass === true) {\r
34574 viewportClass = 'Viewport';\r
34575 } else {\r
34576 requires.push('Ext.plugin.Viewport');\r
34577 }\r
34578 Controller.processDependencies(proto, requires, namespace, 'view', viewportClass);\r
34579 }\r
34580 },\r
34581 onBeforeLaunch: function() {\r
34582 var me = this,\r
34583 autoCreateViewport = me.autoCreateViewport;\r
34584 if (me.getEnableQuickTips()) {\r
34585 me.initQuickTips();\r
34586 }\r
34587 if (autoCreateViewport) {\r
34588 me.initViewport();\r
34589 }\r
34590 this.callParent(arguments);\r
34591 },\r
34592 getViewportName: function() {\r
34593 var name = null,\r
34594 autoCreate = this.autoCreateViewport;\r
34595 if (autoCreate) {\r
34596 name = (autoCreate === true) ? 'Viewport' : autoCreate;\r
34597 }\r
34598 return name;\r
34599 },\r
34600 initViewport: function() {\r
34601 this.setMainView(this.getViewportName());\r
34602 },\r
34603 initQuickTips: function() {\r
34604 Ext.tip.QuickTipManager.init();\r
34605 }\r
34606});\r
34607\r
34608Ext.define('Ext.overrides.dom.Helper', (function() {\r
34609 var tableRe = /^(?:table|thead|tbody|tr|td)$/i,\r
34610 tableElRe = /td|tr|tbody|thead/i,\r
34611 ts = '<table>',\r
34612 te = '</table>',\r
34613 tbs = ts + '<tbody>',\r
34614 tbe = '</tbody>' + te,\r
34615 trs = tbs + '<tr>',\r
34616 tre = '</tr>' + tbe;\r
34617 return {\r
34618 override: 'Ext.dom.Helper',\r
34619 ieInsertHtml: function(where, el, html) {\r
34620 var frag = null;\r
34621 // IE's incomplete table implementation: http://www.ericvasilik.com/2006/07/code-karma.html\r
34622 if (Ext.isIE9m && tableRe.test(el.tagName)) {\r
34623 frag = this.insertIntoTable(el.tagName.toLowerCase(), where, el, html);\r
34624 }\r
34625 return frag;\r
34626 },\r
34627 ieOverwrite: function(el, html) {\r
34628 // IE Inserting HTML into a table/tbody/tr requires extra processing:\r
34629 // http://www.ericvasilik.com/2006/07/code-karma.html\r
34630 if (Ext.isIE9m && tableRe.test(el.tagName)) {\r
34631 // Clearing table elements requires removal of all elements.\r
34632 while (el.firstChild) {\r
34633 el.removeChild(el.firstChild);\r
34634 }\r
34635 if (html) {\r
34636 return this.insertHtml('afterbegin', el, html);\r
34637 }\r
34638 }\r
34639 },\r
34640 ieTable: function(depth, openingTags, htmlContent, closingTags) {\r
34641 var i = -1,\r
34642 el = this.detachedDiv,\r
34643 ns, nx;\r
34644 el.innerHTML = [\r
34645 openingTags,\r
34646 htmlContent,\r
34647 closingTags\r
34648 ].join('');\r
34649 while (++i < depth) {\r
34650 el = el.firstChild;\r
34651 }\r
34652 // If the result is multiple siblings, then encapsulate them into one fragment.\r
34653 ns = el.nextSibling;\r
34654 if (ns) {\r
34655 ns = el;\r
34656 el = document.createDocumentFragment();\r
34657 while (ns) {\r
34658 nx = ns.nextSibling;\r
34659 el.appendChild(ns);\r
34660 ns = nx;\r
34661 }\r
34662 }\r
34663 return el;\r
34664 },\r
34665 /**
34666 * @private
34667 * @method insertIntoTable
34668 * @member Ext.dom.Helper
34669 * workaround for broken table implementation in IE9m
34670 * http://www.ericvasilik.com/2006/07/code-karma.html
34671 */\r
34672 insertIntoTable: function(tag, where, destinationEl, html) {\r
34673 var node, before,\r
34674 bb = where === 'beforebegin',\r
34675 ab = where === 'afterbegin',\r
34676 be = where === 'beforeend',\r
34677 ae = where === 'afterend';\r
34678 if (tag === 'td' && (ab || be) || !tableElRe.test(tag) && (bb || ae)) {\r
34679 return null;\r
34680 }\r
34681 before = bb ? destinationEl : ae ? destinationEl.nextSibling : ab ? destinationEl.firstChild : null;\r
34682 if (bb || ae) {\r
34683 destinationEl = destinationEl.parentNode;\r
34684 }\r
34685 if (tag === 'td' || (tag === 'tr' && (be || ab))) {\r
34686 node = this.ieTable(4, trs, html, tre);\r
34687 } else if (((tag === 'tbody' || tag === 'thead') && (be || ab)) || (tag === 'tr' && (bb || ae))) {\r
34688 node = this.ieTable(3, tbs, html, tbe);\r
34689 } else {\r
34690 node = this.ieTable(2, ts, html, te);\r
34691 }\r
34692 destinationEl.insertBefore(node, before);\r
34693 return node;\r
34694 }\r
34695 };\r
34696})());\r
34697\r
34698Ext.define('Ext.overrides.list.TreeItem', {\r
34699 override: 'Ext.list.TreeItem',\r
34700 createFloater: function() {\r
34701 var me = this,\r
34702 owner = me.getOwner(),\r
34703 ui = owner.getUi(),\r
34704 cls = Ext.baseCSSPrefix + 'treelist',\r
34705 floater;\r
34706 if (ui) {\r
34707 cls += ' ' + cls + '-' + ui;\r
34708 }\r
34709 me.floater = floater = new Ext.container.Container({\r
34710 cls: cls + ' ' + Ext.baseCSSPrefix + 'treelist-floater',\r
34711 floating: true,\r
34712 width: 200,\r
34713 shadow: false,\r
34714 renderTo: Ext.getBody(),\r
34715 listeners: {\r
34716 element: 'el',\r
34717 click: function(e) {\r
34718 return owner.onClick(e);\r
34719 }\r
34720 }\r
34721 });\r
34722 floater.add(me);\r
34723 floater.show();\r
34724 floater.el.alignTo(me.getToolElement(), 'tr?');\r
34725 return floater;\r
34726 },\r
34727 runAnimation: function(animation) {\r
34728 return this.itemContainer.addAnimation(animation);\r
34729 },\r
34730 stopAnimation: function(animation) {\r
34731 animation.jumpToEnd();\r
34732 }\r
34733});\r
34734\r
34735/**
34736 *
34737 */\r
34738Ext.define('Ext.overrides.plugin.Abstract', {\r
34739 override: 'Ext.plugin.Abstract',\r
34740 $configStrict: false,\r
34741 $configPrefixed: false,\r
34742 disabled: false,\r
34743 /**
34744 * @cfg {String|Array} stateEvents
34745 * The configured list of stateEvents used to (optionally) participate in Owner Component's state management.
34746 * @member Ext.plugin.Abstract
34747 */\r
34748 /**
34749 * @method
34750 * The getState method is invoked by the client Component's State mixin when one or more of the the specified {@link #stateEvents} are raised.
34751 *
34752 * The supplied implementation is empty. If plugin Subclasses are to (optionally) participate in the client Component's
34753 * state management, implementers should provide a suitable method which returns a state object.
34754 * @return {Object} state
34755 * @member Ext.plugin.Abstract
34756 */\r
34757 getState: null,\r
34758 /**
34759 * @method
34760 * The applyState method is invoked by the client Component's State mixin after initComponent method has been run for the client.
34761 *
34762 * The supplied implementation is empty. If plugin Subclasses are to (optionally) participate in the client Component's
34763 * state management, implementers should provide a suitable method to utilize it.
34764 * @param {Object} state The current plugin state object to be applied.
34765 * @param {Object} allState The current aggregate state of the Component and all plugins.
34766 * @member Ext.plugin.Abstract
34767 */\r
34768 applyState: null,\r
34769 /**
34770 * The base implementation just sets the plugin's `disabled` flag to `false`
34771 *
34772 * Plugin subclasses which need more complex processing may implement an overriding implementation.
34773 * @member Ext.plugin.Abstract
34774 */\r
34775 enable: function() {\r
34776 this.disabled = false;\r
34777 },\r
34778 /**
34779 * The base implementation just sets the plugin's `disabled` flag to `true`
34780 *
34781 * Plugin subclasses which need more complex processing may implement an overriding implementation.
34782 * @member Ext.plugin.Abstract
34783 */\r
34784 disable: function() {\r
34785 this.disabled = true;\r
34786 }\r
34787});\r
34788\r
34789/**
34790 * @class Ext.app.ViewController
34791 */\r
34792/**
34793 * @method beforeRender
34794 * @template
34795 * Template method called by the owning component's
34796 * {@link Ext.Component#method-beforeRender beforeRender} method.
34797 * @param {Ext.Component} component The owner component attached to the
34798 * ViewController
34799 */\r
34800/**
34801 * @method afterRender
34802 * @template
34803 * Template method called by the owning component's
34804 * {@link Ext.Component#method-afterRender afterRender} method.
34805 * @param {Ext.Component} component The owner component attached to the
34806 * ViewController
34807 */\r
34808/**
34809 * @method boxReady
34810 * @template
34811 * Template method called by the owning component's
34812 * {@link Ext.Component#method-onBoxReady onBoxReady} method.
34813 * @param {Ext.Component} component The owner component attached to the
34814 * ViewController
34815 */\r
34816\r
34817Ext.define(null, {\r
34818 override: 'Ext.event.publisher.Focus',\r
34819 compatibility: Ext.isIE10m,\r
34820 doDelegatedEvent: function(e, invokeAfter) {\r
34821 var body = document.body,\r
34822 el = Ext.synchronouslyFocusing;\r
34823 // This horrid hack is necessary to work around the issue with input elements\r
34824 // in IE10m that can fail to focus under certain conditions. See comment in\r
34825 // Ext.dom.Element override.\r
34826 if (el && ((e.type === 'focusout' && e.srcElement === el && e.toElement === body) || (e.type === 'focusin' && e.srcElement === body && e.fromElement === el && e.toElement === null))) {\r
34827 return;\r
34828 }\r
34829 \r
34830 return this.callParent([\r
34831 e,\r
34832 invokeAfter\r
34833 ]);\r
34834 }\r
34835});\r
34836\r
34837Ext.define(null, {\r
34838 override: 'Ext.scroll.DomScroller',\r
34839 compatibility: Ext.isIE8,\r
34840 privates: {\r
34841 // Important note: this code had to be copied as a whole\r
34842 // because the scrollLeft assignment trickery only works\r
34843 // reliably when it is done within the same function context.\r
34844 doScrollTo: function(x, y, animate) {\r
34845 var me = this,\r
34846 element = me.getElement(),\r
34847 maxPosition, dom, to, xInf, yInf;\r
34848 if (element && !element.destroyed) {\r
34849 dom = this.getElement().dom;\r
34850 xInf = (x === Infinity);\r
34851 yInf = (y === Infinity);\r
34852 if (xInf || yInf) {\r
34853 maxPosition = me.getMaxPosition();\r
34854 if (xInf) {\r
34855 x = maxPosition.x;\r
34856 }\r
34857 if (yInf) {\r
34858 y = maxPosition.y;\r
34859 }\r
34860 }\r
34861 x = me.convertX(x);\r
34862 if (animate) {\r
34863 to = {};\r
34864 if (y != null) {\r
34865 to.scrollTop = y;\r
34866 }\r
34867 if (x != null) {\r
34868 to.scrollLeft = x;\r
34869 }\r
34870 element.animate(Ext.mergeIf({\r
34871 to: {\r
34872 scrollTop: y,\r
34873 scrollLeft: x\r
34874 }\r
34875 }, animate));\r
34876 } else {\r
34877 // When we need to assign both scrollTop and scrollLeft,\r
34878 // IE8 might fire scroll event on the first assignment\r
34879 // but not on the second; that behavior is unlike the other\r
34880 // browsers which will wait for the second assignment\r
34881 // to happen before firing the event. This leads to our\r
34882 // scrollstart event firing prematurely, when the scrolling\r
34883 // has not actually finished yet.\r
34884 // To work around that, we ignore the first event and then\r
34885 // force another one by assigning scrollLeft the second time.\r
34886 if (x != null && y != null) {\r
34887 me.deferDomScroll = true;\r
34888 }\r
34889 if (y != null) {\r
34890 dom.scrollTop = y;\r
34891 }\r
34892 if (x != null) {\r
34893 dom.scrollLeft = x;\r
34894 }\r
34895 if (me.deferDomScroll) {\r
34896 me.deferDomScroll = false;\r
34897 // Reading the DOM makes sure the second assignment\r
34898 // will fire the event.\r
34899 +dom.scrollLeft;\r
34900 dom.scrollLeft = x;\r
34901 }\r
34902 }\r
34903 // Our position object will need refreshing before returning.\r
34904 me.positionDirty = true;\r
34905 }\r
34906 },\r
34907 onDomScroll: function() {\r
34908 var me = this;\r
34909 if (me.deferDomScroll) {\r
34910 return;\r
34911 }\r
34912 me.callParent();\r
34913 }\r
34914 }\r
34915});\r
34916\r