]> git.proxmox.com Git - extjs.git/blame - extjs/packages/core/src/class/Base.js
add extjs 6.0.1 sources
[extjs.git] / extjs / packages / core / src / class / Base.js
CommitLineData
6527f429
DM
1// @tag class\r
2/**\r
3 * @class Ext.Base\r
4 *\r
5 * The root of all classes created with {@link Ext#define}.\r
6 *\r
7 * Ext.Base is the building block of all Ext classes. All classes in Ext inherit from Ext.Base.\r
8 * All prototype and static members of this class are inherited by all other classes.\r
9 */\r
10Ext.Base = (function(flexSetter) {\r
11// @define Ext.Base\r
12// @require Ext.Util\r
13// @require Ext.Version\r
14// @require Ext.Configurator\r
15// @uses Ext.ClassManager\r
16var noArgs = [],\r
17 baseStaticMember,\r
18 baseStaticMembers = [],\r
19 getConfig = function (name, peek) {\r
20 var me = this,\r
21 ret, cfg, getterName;\r
22\r
23 if (name) {\r
24 cfg = Ext.Config.map[name];\r
25 //<debug>\r
26 if (!cfg) {\r
27 Ext.Logger.error("Invalid property name for getter: '" + name + "' for '" + me.$className + "'.");\r
28 }\r
29 //</debug>\r
30 getterName = cfg.names.get;\r
31 if (peek && me.hasOwnProperty(getterName)) {\r
32 ret = me.config[name];\r
33 } else {\r
34 ret = me[getterName]();\r
35 }\r
36 } else {\r
37 ret = me.getCurrentConfig();\r
38 }\r
39 return ret;\r
40 },\r
41 //<debug>\r
42 makeDeprecatedMethod = function (oldName, newName, msg) {\r
43 var message = '"'+ oldName +'" is deprecated.';\r
44\r
45 if (msg) {\r
46 message += ' ' + msg;\r
47 } else if (newName) {\r
48 message += ' Please use "'+ newName +'" instead.';\r
49 }\r
50\r
51 return function () {\r
52 Ext.raise(message);\r
53 };\r
54 },\r
55 addDeprecatedProperty = function (object, oldName, newName, message) {\r
56 if (!message) {\r
57 message = '"' + oldName + '" is deprecated.';\r
58 }\r
59 if (newName) {\r
60 message += ' Please use "' + newName + '" instead.';\r
61 }\r
62\r
63 if (message) {\r
64 Ext.Object.defineProperty(object, oldName, {\r
65 get: function() {\r
66 Ext.raise(message);\r
67 },\r
68 set: function(value) {\r
69 Ext.raise(message);\r
70 },\r
71 configurable: true\r
72 });\r
73 }\r
74 },\r
75 //</debug>\r
76 makeAliasFn = function (name) {\r
77 return function () {\r
78 return this[name].apply(this, arguments);\r
79 };\r
80 },\r
81 Version = Ext.Version,\r
82 leadingDigitRe = /^\d/,\r
83 oneMember = {},\r
84 aliasOneMember = {},\r
85 Base = function(){},\r
86 BasePrototype = Base.prototype;\r
87\r
88 // These static properties will be copied to every newly created class with {@link Ext#define}\r
89 Ext.apply(Base, {\r
90 $className: 'Ext.Base',\r
91\r
92 $isClass: true,\r
93\r
94 /**\r
95 * Create a new instance of this Class.\r
96 *\r
97 * Ext.define('My.cool.Class', {\r
98 * ...\r
99 * });\r
100 *\r
101 * My.cool.Class.create({\r
102 * someConfig: true\r
103 * });\r
104 *\r
105 * All parameters are passed to the constructor of the class.\r
106 *\r
107 * @return {Object} the created instance.\r
108 * @static\r
109 * @inheritable\r
110 */\r
111 create: function() {\r
112 return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));\r
113 },\r
114\r
115 /**\r
116 * This method applies a versioned, deprecation declaration to this class. This\r
117 * is typically called by the `deprecated` config.\r
118 * @private\r
119 */\r
120 addDeprecations: function (deprecations) {\r
121 var me = this,\r
122 all = [],\r
123 compatVersion = Ext.getCompatVersion(deprecations.name),\r
124 //<debug>\r
125 configurator = me.getConfigurator(),\r
126 displayName = (me.$className || '') + '#',\r
127 //</debug>\r
128 deprecate, versionSpec, index, message, target,\r
129 enabled, existing, fn, names, oldName, newName, member, statics, version;\r
130\r
131 for (versionSpec in deprecations) {\r
132 if (leadingDigitRe.test(versionSpec)) {\r
133 version = new Ext.Version(versionSpec);\r
134 version.deprecations = deprecations[versionSpec];\r
135 all.push(version);\r
136 }\r
137 }\r
138\r
139 all.sort(Version.compare);\r
140\r
141 for (index = all.length; index--; ) {\r
142 deprecate = (version = all[index]).deprecations;\r
143 target = me.prototype;\r
144 statics = deprecate.statics;\r
145\r
146 // If user specifies, say 4.2 compatibility and we have a 5.0 deprecation\r
147 // then that block needs to be "enabled" to "revert" to behaviors prior\r
148 // to 5.0. By default, compatVersion === currentVersion, so there are no\r
149 // enabled blocks. In dev mode we still want to visit all the blocks and\r
150 // possibly add shims to detect use of deprecated methods, but in a build\r
151 // (if the deprecated block remains somehow) we just break the loop.\r
152 enabled = compatVersion && compatVersion.lt(version);\r
153\r
154 //<debug>\r
155 if (!enabled) {} else\r
156 //</debug>\r
157 if (!enabled) {\r
158 // we won't get here in dev mode when !enabled\r
159 break;\r
160 }\r
161\r
162 while (deprecate) {\r
163 names = deprecate.methods;\r
164 if (names) {\r
165 for (oldName in names) {\r
166 member = names[oldName];\r
167 fn = null;\r
168\r
169 if (!member) {\r
170 /*\r
171 * Something like:\r
172 *\r
173 * '5.1': {\r
174 * methods: {\r
175 * removedMethod: null\r
176 * }\r
177 * }\r
178 *\r
179 * Since there is no recovering the method, we always put\r
180 * on a shim to catch abuse.\r
181 */\r
182\r
183 //<debug>\r
184 // The class should not already have a method by the oldName\r
185 Ext.Assert.isNotDefinedProp(target, oldName);\r
186\r
187 fn = makeDeprecatedMethod(displayName + oldName);\r
188 //</debug>\r
189 } else if (Ext.isString(member)) {\r
190 /*\r
191 * Something like:\r
192 *\r
193 * '5.1': {\r
194 * methods: {\r
195 * oldName: 'newName'\r
196 * }\r
197 * }\r
198 *\r
199 * If this block is enabled, we just put an alias in place.\r
200 * Otherwise we need to inject a\r
201 */\r
202\r
203 //<debug>\r
204 // The class should not already have a method by the oldName\r
205 Ext.Assert.isNotDefinedProp(target, oldName);\r
206 Ext.Assert.isDefinedProp(target, member);\r
207 //</debug>\r
208\r
209 if (enabled) {\r
210 // This call to the real method name must be late\r
211 // bound if it is to pick up overrides and such.\r
212 fn = makeAliasFn(member);\r
213 }\r
214 //<debug>\r
215 else {\r
216 fn = makeDeprecatedMethod(displayName + oldName, member);\r
217 }\r
218 //</debug>\r
219 } else {\r
220 /*\r
221 * Something like:\r
222 *\r
223 * '5.1': {\r
224 * methods: {\r
225 * foo: function () { ... }\r
226 * }\r
227 * }\r
228 *\r
229 * Or this:\r
230 *\r
231 * '5.1': {\r
232 * methods: {\r
233 * foo: {\r
234 * fn: function () { ... },\r
235 * message: 'Please use "bar" instead.'\r
236 * }\r
237 * }\r
238 * }\r
239 *\r
240 * Or just this:\r
241 *\r
242 * '5.1': {\r
243 * methods: {\r
244 * foo: {\r
245 * message: 'Use something else instead.'\r
246 * }\r
247 * }\r
248 * }\r
249 *\r
250 * If this block is enabled, and "foo" is an existing\r
251 * method, than we apply the given method as an override.\r
252 * If "foo" is not existing, we simply add the method.\r
253 *\r
254 * If the block is not enabled and there is no existing\r
255 * method by that name, than we add a shim to prevent\r
256 * abuse.\r
257 */\r
258 message = '';\r
259 if (member.message || member.fn) {\r
260 //<debug>\r
261 message = member.message;\r
262 //</debug>\r
263 member = member.fn;\r
264 }\r
265\r
266 existing = target.hasOwnProperty(oldName) && target[oldName];\r
267\r
268 if (enabled && member) {\r
269 member.$owner = me;\r
270 member.$name = oldName;\r
271 //<debug>\r
272 member.name = displayName + oldName;\r
273 //</debug>\r
274 if (existing) {\r
275 member.$previous = existing;\r
276 }\r
277\r
278 fn = member;\r
279 }\r
280 //<debug>\r
281 else if (!existing) {\r
282 fn = makeDeprecatedMethod(displayName + oldName, null,\r
283 message);\r
284 }\r
285 //</debug>\r
286 }\r
287\r
288 if (fn) {\r
289 target[oldName] = fn;\r
290 }\r
291 } // for oldName\r
292 }\r
293\r
294 //-------------------------------------\r
295 // Debug only\r
296 //<debug>\r
297\r
298 names = deprecate.configs;\r
299 if (names) {\r
300 //\r
301 // '6.0': {\r
302 // configs: {\r
303 // dead: null,\r
304 //\r
305 // renamed: 'newName',\r
306 //\r
307 // removed: {\r
308 // message: 'This config was replaced by pixie dust'\r
309 // }\r
310 // }\r
311 // }\r
312 //\r
313 configurator.addDeprecations(names);\r
314 }\r
315\r
316 names = deprecate.properties;\r
317 if (names && !enabled) {\r
318 // For properties about the only thing we can do is (on Good\r
319 // Browsers), add warning shims for accessing them. So if the\r
320 // block is enabled, we don't want those.\r
321 for (oldName in names) {\r
322 newName = names[oldName];\r
323\r
324 if (Ext.isString(newName)) {\r
325 addDeprecatedProperty(target, displayName + oldName, newName);\r
326 } else if (newName && newName.message) {\r
327 addDeprecatedProperty(target, displayName + oldName, null,\r
328 newName.message);\r
329 } else {\r
330 addDeprecatedProperty(target, displayName + oldName);\r
331 }\r
332 }\r
333 }\r
334\r
335 //</debug>\r
336 //-------------------------------------\r
337\r
338 // reset to handle statics and apply them to the class\r
339 deprecate = statics;\r
340 statics = null;\r
341 target = me;\r
342 }\r
343 }\r
344 },\r
345\r
346 /**\r
347 * @private\r
348 * @static\r
349 * @inheritable\r
350 * @param config\r
351 */\r
352 extend: function(parent) {\r
353 var me = this,\r
354 parentPrototype = parent.prototype,\r
355 prototype, i, ln, name, statics;\r
356\r
357 prototype = me.prototype = Ext.Object.chain(parentPrototype);\r
358 prototype.self = me;\r
359\r
360 me.superclass = prototype.superclass = parentPrototype;\r
361\r
362 if (!parent.$isClass) {\r
363 for (i in BasePrototype) {\r
364 if (i in prototype) {\r
365 prototype[i] = BasePrototype[i];\r
366 }\r
367 }\r
368 }\r
369\r
370 //<feature classSystem.inheritableStatics>\r
371 // Statics inheritance\r
372 statics = parentPrototype.$inheritableStatics;\r
373\r
374 if (statics) {\r
375 for (i = 0,ln = statics.length; i < ln; i++) {\r
376 name = statics[i];\r
377\r
378 if (!me.hasOwnProperty(name)) {\r
379 me[name] = parent[name];\r
380 }\r
381 }\r
382 }\r
383 //</feature>\r
384\r
385 if (parent.$onExtended) {\r
386 me.$onExtended = parent.$onExtended.slice();\r
387 }\r
388\r
389 //<feature classSystem.config>\r
390 me.getConfigurator();\r
391 //</feature>\r
392 },\r
393\r
394 /**\r
395 * @private\r
396 * @static\r
397 * @inheritable\r
398 */\r
399 $onExtended: [],\r
400\r
401 /**\r
402 * @private\r
403 * @static\r
404 * @inheritable\r
405 */\r
406 triggerExtended: function() {\r
407 //<debug>\r
408 Ext.classSystemMonitor && Ext.classSystemMonitor(this, 'Ext.Base#triggerExtended', arguments);\r
409 //</debug>\r
410 \r
411 var callbacks = this.$onExtended,\r
412 ln = callbacks.length,\r
413 i, callback;\r
414\r
415 if (ln > 0) {\r
416 for (i = 0; i < ln; i++) {\r
417 callback = callbacks[i];\r
418 callback.fn.apply(callback.scope || this, arguments);\r
419 }\r
420 }\r
421 },\r
422\r
423 /**\r
424 * @private\r
425 * @static\r
426 * @inheritable\r
427 */\r
428 onExtended: function(fn, scope) {\r
429 this.$onExtended.push({\r
430 fn: fn,\r
431 scope: scope\r
432 });\r
433\r
434 return this;\r
435 },\r
436\r
437 /**\r
438 * Add / override static properties of this class.\r
439 *\r
440 * Ext.define('My.cool.Class', {\r
441 * ...\r
442 * });\r
443 *\r
444 * My.cool.Class.addStatics({\r
445 * someProperty: 'someValue', // My.cool.Class.someProperty = 'someValue'\r
446 * method1: function() { ... }, // My.cool.Class.method1 = function() { ... };\r
447 * method2: function() { ... } // My.cool.Class.method2 = function() { ... };\r
448 * });\r
449 *\r
450 * @param {Object} members\r
451 * @return {Ext.Base} this\r
452 * @static\r
453 * @inheritable\r
454 */\r
455 addStatics: function (members) {\r
456 this.addMembers(members, true);\r
457 return this;\r
458 },\r
459\r
460 /**\r
461 * @private\r
462 * @static\r
463 * @inheritable\r
464 * @param {Object} members\r
465 */\r
466 addInheritableStatics: function(members) {\r
467 var inheritableStatics,\r
468 hasInheritableStatics,\r
469 prototype = this.prototype,\r
470 name, member;\r
471\r
472 inheritableStatics = prototype.$inheritableStatics;\r
473 hasInheritableStatics = prototype.$hasInheritableStatics;\r
474\r
475 if (!inheritableStatics) {\r
476 inheritableStatics = prototype.$inheritableStatics = [];\r
477 hasInheritableStatics = prototype.$hasInheritableStatics = {};\r
478 }\r
479\r
480 //<debug>\r
481 var className = Ext.getClassName(this) + '.';\r
482 //</debug>\r
483\r
484 for (name in members) {\r
485 if (members.hasOwnProperty(name)) {\r
486 member = members[name];\r
487 //<debug>\r
488 if (typeof member == 'function') {\r
489 member.name = className + name;\r
490 }\r
491 //</debug>\r
492 this[name] = member;\r
493\r
494 if (!hasInheritableStatics[name]) {\r
495 hasInheritableStatics[name] = true;\r
496 inheritableStatics.push(name);\r
497 }\r
498 }\r
499 }\r
500\r
501 return this;\r
502 },\r
503\r
504 /**\r
505 * Add methods / properties to the prototype of this class.\r
506 *\r
507 * Ext.define('My.awesome.Cat', {\r
508 * constructor: function() {\r
509 * ...\r
510 * }\r
511 * });\r
512 *\r
513 * My.awesome.Cat.addMembers({\r
514 * meow: function() {\r
515 * alert('Meowww...');\r
516 * }\r
517 * });\r
518 *\r
519 * var kitty = new My.awesome.Cat();\r
520 * kitty.meow();\r
521 *\r
522 * @param {Object} members The members to add to this class.\r
523 * @param {Boolean} [isStatic=false] Pass `true` if the members are static.\r
524 * @param {Boolean} [privacy=false] Pass `true` if the members are private. This\r
525 * only has meaning in debug mode and only for methods.\r
526 * @static\r
527 * @inheritable\r
528 */\r
529 addMembers: function (members, isStatic, privacy) {\r
530 var me = this, // this class\r
531 cloneFunction = Ext.Function.clone,\r
532 target = isStatic ? me : me.prototype,\r
533 defaultConfig = !isStatic && target.defaultConfig,\r
534 enumerables = Ext.enumerables,\r
535 privates = members.privates,\r
536 configs, i, ln, member, name, subPrivacy, privateStatics;\r
537\r
538 //<debug>\r
539 var displayName = (me.$className || '') + '#';\r
540 //</debug>\r
541\r
542 if (privates) {\r
543 // This won't run for normal class private members but will pick up all\r
544 // others (statics, overrides, etc).\r
545 delete members.privates;\r
546 if (!isStatic) {\r
547 privateStatics = privates.statics;\r
548 delete privates.statics;\r
549 }\r
550 \r
551 //<debug>\r
552 subPrivacy = privates.privacy || privacy || 'framework';\r
553 //</debug>\r
554\r
555 me.addMembers(privates, isStatic, subPrivacy);\r
556 if (privateStatics) {\r
557 me.addMembers(privateStatics, true, subPrivacy);\r
558 }\r
559 }\r
560\r
561 for (name in members) {\r
562 if (members.hasOwnProperty(name)) {\r
563 member = members[name];\r
564\r
565 //<debug>\r
566 if (privacy === true) {\r
567 privacy = 'framework';\r
568 }\r
569 if (member && member.$nullFn && privacy !== member.$privacy) {\r
570 Ext.raise('Cannot use stock function for private method ' +\r
571 (me.$className ? me.$className + '#' : '') + name);\r
572 }\r
573 //</debug>\r
574\r
575 if (typeof member === 'function' && !member.$isClass && !member.$nullFn) {\r
576 if (member.$owner) {\r
577 member = cloneFunction(member);\r
578 }\r
579\r
580 if (target.hasOwnProperty(name)) {\r
581 member.$previous = target[name];\r
582 }\r
583\r
584 // This information is needed by callParent() and callSuper() as\r
585 // well as statics() and even Ext.fly().\r
586 member.$owner = me;\r
587 member.$name = name;\r
588\r
589 //<debug>\r
590 member.name = displayName + name;\r
591\r
592 var existing = target[name];\r
593\r
594 if (privacy) {\r
595 member.$privacy = privacy;\r
596\r
597 // The general idea here is that an existing, non-private\r
598 // method can be marked private. This is because the other\r
599 // way is strictly forbidden (private method going public)\r
600 // so if a method is in that gray area it can only be made\r
601 // private in doc form which allows a derived class to make\r
602 // it public.\r
603 if (existing && existing.$privacy && existing.$privacy !== privacy) {\r
604 Ext.privacyViolation(me, existing, member, isStatic);\r
605 }\r
606 } else if (existing && existing.$privacy) {\r
607 Ext.privacyViolation(me, existing, member, isStatic);\r
608 }\r
609 //</debug>\r
610 // The last part of the check here resolves a conflict if we have the same property\r
611 // declared as both a config and a member on the class so that the config wins.\r
612 } else if (defaultConfig && (name in defaultConfig) && !target.config.hasOwnProperty(name)) {\r
613 // This is a config property so it must be added to the configs\r
614 // collection not just smashed on the prototype...\r
615 (configs || (configs = {}))[name] = member;\r
616 continue;\r
617 }\r
618\r
619 target[name] = member;\r
620 }\r
621 }\r
622\r
623 if (configs) {\r
624 // Add any configs found in the normal members arena:\r
625 me.addConfig(configs);\r
626 }\r
627\r
628 if (enumerables) {\r
629 for (i = 0, ln = enumerables.length; i < ln; ++i) {\r
630 if (members.hasOwnProperty(name = enumerables[i])) {\r
631 member = members[name];\r
632\r
633 // The enumerables are all functions...\r
634 if (member && !member.$nullFn) {\r
635 if (member.$owner) {\r
636 member = cloneFunction(member);\r
637 }\r
638\r
639 member.$owner = me;\r
640 member.$name = name;\r
641 //<debug>\r
642 member.name = displayName + name;\r
643 //</debug>\r
644\r
645 if (target.hasOwnProperty(name)) {\r
646 member.$previous = target[name];\r
647 }\r
648 }\r
649\r
650 target[name] = member;\r
651 }\r
652 }\r
653 }\r
654\r
655 return this;\r
656 },\r
657\r
658 /**\r
659 * @private\r
660 * @static\r
661 * @inheritable\r
662 * @param name\r
663 * @param member\r
664 */\r
665 addMember: function (name, member) {\r
666 oneMember[name] = member;\r
667 this.addMembers(oneMember);\r
668 delete oneMember[name];\r
669 return this;\r
670 },\r
671\r
672 /**\r
673 * Borrow another class' members to the prototype of this class.\r
674 *\r
675 * Ext.define('Bank', {\r
676 * money: '$$$',\r
677 * printMoney: function() {\r
678 * alert('$$$$$$$');\r
679 * }\r
680 * });\r
681 *\r
682 * Ext.define('Thief', {\r
683 * ...\r
684 * });\r
685 *\r
686 * Thief.borrow(Bank, ['money', 'printMoney']);\r
687 *\r
688 * var steve = new Thief();\r
689 *\r
690 * alert(steve.money); // alerts '$$$'\r
691 * steve.printMoney(); // alerts '$$$$$$$'\r
692 *\r
693 * @param {Ext.Base} fromClass The class to borrow members from\r
694 * @param {Array/String} members The names of the members to borrow\r
695 * @return {Ext.Base} this\r
696 * @static\r
697 * @inheritable\r
698 * @private\r
699 */\r
700 borrow: function(fromClass, members) {\r
701 //<debug>\r
702 Ext.classSystemMonitor && Ext.classSystemMonitor(this, 'Ext.Base#borrow', arguments);\r
703 //</debug>\r
704\r
705 var prototype = fromClass.prototype,\r
706 membersObj = {},\r
707 i, ln, name;\r
708\r
709 members = Ext.Array.from(members);\r
710\r
711 for (i = 0,ln = members.length; i < ln; i++) {\r
712 name = members[i];\r
713 membersObj[name] = prototype[name];\r
714 }\r
715\r
716 return this.addMembers(membersObj);\r
717 },\r
718\r
719 /**\r
720 * Override members of this class. Overridden methods can be invoked via\r
721 * {@link Ext.Base#callParent}.\r
722 *\r
723 * Ext.define('My.Cat', {\r
724 * constructor: function() {\r
725 * alert("I'm a cat!");\r
726 * }\r
727 * });\r
728 *\r
729 * My.Cat.override({\r
730 * constructor: function() {\r
731 * alert("I'm going to be a cat!");\r
732 *\r
733 * this.callParent(arguments);\r
734 *\r
735 * alert("Meeeeoooowwww");\r
736 * }\r
737 * });\r
738 *\r
739 * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"\r
740 * // alerts "I'm a cat!"\r
741 * // alerts "Meeeeoooowwww"\r
742 *\r
743 * Direct use of this method should be rare. Use {@link Ext#define Ext.define}\r
744 * instead:\r
745 *\r
746 * Ext.define('My.CatOverride', {\r
747 * override: 'My.Cat',\r
748 * constructor: function() {\r
749 * alert("I'm going to be a cat!");\r
750 *\r
751 * this.callParent(arguments);\r
752 *\r
753 * alert("Meeeeoooowwww");\r
754 * }\r
755 * });\r
756 *\r
757 * The above accomplishes the same result but can be managed by the {@link Ext.Loader}\r
758 * which can properly order the override and its target class and the build process\r
759 * can determine whether the override is needed based on the required state of the\r
760 * target class (My.Cat).\r
761 *\r
762 * @param {Object} members The properties to add to this class. This should be\r
763 * specified as an object literal containing one or more properties.\r
764 * @return {Ext.Base} this class\r
765 * @static\r
766 * @inheritable\r
767 */\r
768 override: function(members) {\r
769 var me = this,\r
770 statics = members.statics,\r
771 inheritableStatics = members.inheritableStatics,\r
772 config = members.config,\r
773 mixins = members.mixins,\r
774 cachedConfig = members.cachedConfig;\r
775\r
776 if (statics || inheritableStatics || config) {\r
777 members = Ext.apply({}, members);\r
778 }\r
779\r
780 if (statics) {\r
781 me.addMembers(statics, true);\r
782 delete members.statics;\r
783 }\r
784\r
785 if (inheritableStatics){\r
786 me.addInheritableStatics(inheritableStatics);\r
787 delete members.inheritableStatics;\r
788 }\r
789\r
790 if (config) {\r
791 me.addConfig(config);\r
792 delete members.config;\r
793 }\r
794 \r
795 if (cachedConfig) {\r
796 me.addCachedConfig(cachedConfig);\r
797 delete members.cachedConfig;\r
798 }\r
799 \r
800 delete members.mixins;\r
801\r
802 me.addMembers(members);\r
803 if (mixins) {\r
804 me.mixin(mixins);\r
805 }\r
806 return me;\r
807 },\r
808\r
809 /**\r
810 * @protected\r
811 * @static\r
812 * @inheritable\r
813 */\r
814 callParent: function(args) {\r
815 var method;\r
816\r
817 // This code is intentionally inlined for the least amount of debugger stepping\r
818 return (method = this.callParent.caller) && (method.$previous ||\r
819 ((method = method.$owner ? method : method.caller) &&\r
820 method.$owner.superclass.self[method.$name])).apply(this, args || noArgs);\r
821 },\r
822\r
823 /**\r
824 * @protected\r
825 * @static\r
826 * @inheritable\r
827 */\r
828 callSuper: function(args) {\r
829 var method;\r
830\r
831 // This code is intentionally inlined for the least amount of debugger stepping\r
832 return (method = this.callSuper.caller) &&\r
833 ((method = method.$owner ? method : method.caller) &&\r
834 method.$owner.superclass.self[method.$name]).apply(this, args || noArgs);\r
835 },\r
836\r
837 //<feature classSystem.mixins>\r
838 /**\r
839 * Used internally by the mixins pre-processor\r
840 * @private\r
841 * @static\r
842 * @inheritable\r
843 */\r
844 mixin: function(name, mixinClass) {\r
845 var me = this,\r
846 mixin, prototype, key, statics, i, ln, staticName, mixinValue, mixins;\r
847\r
848 if (typeof name !== 'string') {\r
849 mixins = name;\r
850 if (mixins instanceof Array) {\r
851 for (i = 0,ln = mixins.length; i < ln; i++) {\r
852 mixin = mixins[i];\r
853 me.mixin(mixin.prototype.mixinId || mixin.$className, mixin);\r
854 }\r
855 } else {\r
856 // Not a string or array - process the object form:\r
857 // mixins: {\r
858 // foo: ...\r
859 // }\r
860 for (var mixinName in mixins) {\r
861 me.mixin(mixinName, mixins[mixinName]);\r
862 }\r
863 }\r
864 return;\r
865 }\r
866\r
867 mixin = mixinClass.prototype;\r
868 prototype = me.prototype;\r
869\r
870 if (mixin.onClassMixedIn) {\r
871 mixin.onClassMixedIn.call(mixinClass, me);\r
872 }\r
873\r
874 if (!prototype.hasOwnProperty('mixins')) {\r
875 if ('mixins' in prototype) {\r
876 prototype.mixins = Ext.Object.chain(prototype.mixins);\r
877 }\r
878 else {\r
879 prototype.mixins = {};\r
880 }\r
881 }\r
882\r
883 for (key in mixin) {\r
884 mixinValue = mixin[key];\r
885 if (key === 'mixins') {\r
886 // if 2 superclasses (e.g. a base class and a mixin) of this class both\r
887 // have a mixin with the same id, the first one wins, that is to say,\r
888 // the first mixin's methods to be applied to the prototype will not\r
889 // be overwritten by the second one. Since this is the case we also\r
890 // want to make sure we use the first mixin's prototype as the mixin\r
891 // reference, hence the "applyIf" below. A real world example of this\r
892 // is Ext.Widget which mixes in Ext.mixin.Observable. Ext.Widget can\r
893 // be mixed into subclasses of Ext.Component, which mixes in\r
894 // Ext.util.Observable. In this example, since the first "observable"\r
895 // mixin's methods win, we also want its reference to be preserved.\r
896 Ext.applyIf(prototype.mixins, mixinValue);\r
897 }\r
898 else if (!(key === 'mixinId' || key === 'config') && (prototype[key] === undefined)) {\r
899 prototype[key] = mixinValue;\r
900 }\r
901 }\r
902\r
903 //<feature classSystem.inheritableStatics>\r
904 // Mixin statics inheritance\r
905 statics = mixin.$inheritableStatics;\r
906\r
907 if (statics) {\r
908 for (i = 0, ln = statics.length; i < ln; i++) {\r
909 staticName = statics[i];\r
910\r
911 if (!me.hasOwnProperty(staticName)) {\r
912 me[staticName] = mixinClass[staticName];\r
913 }\r
914 }\r
915 }\r
916 //</feature>\r
917\r
918 //<feature classSystem.config>\r
919 if ('config' in mixin) {\r
920 me.addConfig(mixin.config, mixinClass);\r
921 }\r
922 //</feature>\r
923\r
924 prototype.mixins[name] = mixin;\r
925\r
926 if (mixin.afterClassMixedIn) {\r
927 mixin.afterClassMixedIn.call(mixinClass, me);\r
928 }\r
929\r
930 return me;\r
931 },\r
932 //</feature>\r
933\r
934 //<feature classSystem.config>\r
935 /**\r
936 * Adds new config properties to this class. This is called for classes when they\r
937 * are declared, then for any mixins that class may define and finally for any\r
938 * overrides defined that target the class.\r
939 * \r
940 * @param {Object} config\r
941 * @param {Ext.Class} [mixinClass] The mixin class if the configs are from a mixin.\r
942 * @private\r
943 * @static\r
944 * @inheritable\r
945 */\r
946 addConfig: function (config, mixinClass) {\r
947 var cfg = this.$config || this.getConfigurator();\r
948 cfg.add(config, mixinClass);\r
949 },\r
950\r
951 addCachedConfig: function(config, isMixin) {\r
952 var cached = {},\r
953 key;\r
954 \r
955 for (key in config) {\r
956 cached[key] = {\r
957 cached: true,\r
958 $value: config[key]\r
959 };\r
960 }\r
961 this.addConfig(cached, isMixin);\r
962 },\r
963\r
964 /**\r
965 * Returns the `Ext.Configurator` for this class.\r
966 * \r
967 * @return {Ext.Configurator}\r
968 * @private\r
969 * @static\r
970 * @inheritable\r
971 */\r
972 getConfigurator: function () {\r
973 // the Ext.Configurator ctor will set $config so micro-opt out fn call:\r
974 return this.$config || new Ext.Configurator(this);\r
975 },\r
976 //</feature>\r
977\r
978 /**\r
979 * Get the current class' name in string format.\r
980 *\r
981 * Ext.define('My.cool.Class', {\r
982 * constructor: function() {\r
983 * alert(this.self.getName()); // alerts 'My.cool.Class'\r
984 * }\r
985 * });\r
986 *\r
987 * My.cool.Class.getName(); // 'My.cool.Class'\r
988 *\r
989 * @return {String} className\r
990 * @static\r
991 * @inheritable\r
992 */\r
993 getName: function() {\r
994 return Ext.getClassName(this);\r
995 },\r
996\r
997 /**\r
998 * Create aliases for existing prototype methods. Example:\r
999 *\r
1000 * Ext.define('My.cool.Class', {\r
1001 * method1: function() { ... },\r
1002 * method2: function() { ... }\r
1003 * });\r
1004 *\r
1005 * var test = new My.cool.Class();\r
1006 *\r
1007 * My.cool.Class.createAlias({\r
1008 * method3: 'method1',\r
1009 * method4: 'method2'\r
1010 * });\r
1011 *\r
1012 * test.method3(); // test.method1()\r
1013 *\r
1014 * My.cool.Class.createAlias('method5', 'method3');\r
1015 *\r
1016 * test.method5(); // test.method3() -> test.method1()\r
1017 *\r
1018 * @param {String/Object} alias The new method name, or an object to set multiple aliases. See\r
1019 * {@link Ext.Function#flexSetter flexSetter}\r
1020 * @param {String/Object} origin The original method name\r
1021 * @static\r
1022 * @inheritable\r
1023 * @method\r
1024 */\r
1025 createAlias: flexSetter(function(alias, origin) {\r
1026 aliasOneMember[alias] = function() {\r
1027 return this[origin].apply(this, arguments);\r
1028 };\r
1029 this.override(aliasOneMember);\r
1030 delete aliasOneMember[alias];\r
1031 })\r
1032 });\r
1033\r
1034 // Capture the set of static members on Ext.Base that we want to copy to all\r
1035 // derived classes. This array is used by Ext.Class as well as the optimizer.\r
1036 for (baseStaticMember in Base) {\r
1037 if (Base.hasOwnProperty(baseStaticMember)) {\r
1038 baseStaticMembers.push(baseStaticMember);\r
1039 }\r
1040 }\r
1041\r
1042 Base.$staticMembers = baseStaticMembers;\r
1043\r
1044 //<feature classSystem.config>\r
1045 Base.getConfigurator(); // lazily create now so as not capture in $staticMembers\r
1046 //</feature>\r
1047\r
1048 Base.addMembers({\r
1049 /** @private */\r
1050 $className: 'Ext.Base',\r
1051\r
1052 /**\r
1053 * @property {Boolean} isInstance\r
1054 * This value is `true` and is used to identify plain objects from instances of\r
1055 * a defined class.\r
1056 * @protected\r
1057 * @readonly\r
1058 */\r
1059 isInstance: true,\r
1060\r
1061 /**\r
1062 * @property {Boolean} [$configPrefixed]\r
1063 * The value `true` causes `config` values to be stored on instances using a\r
1064 * property name prefixed with an underscore ("_") character. A value of `false`\r
1065 * stores `config` values as properties using their exact name (no prefix).\r
1066 * @private\r
1067 * @since 5.0.0\r
1068 */\r
1069 $configPrefixed: true,\r
1070 \r
1071 /**\r
1072 * @property {Boolean} [$configStrict]\r
1073 * The value `true` instructs the `initConfig` method to only honor values for\r
1074 * properties declared in the `config` block of a class. When `false`, properties\r
1075 * that are not declared in a `config` block will be placed on the instance.\r
1076 * @private\r
1077 * @since 5.0.0\r
1078 */\r
1079 $configStrict: true,\r
1080\r
1081 /**\r
1082 * @property {Boolean} isConfiguring\r
1083 * This property is set to `true` during the call to `initConfig`.\r
1084 * @protected\r
1085 * @readonly\r
1086 * @since 5.0.0\r
1087 */\r
1088 isConfiguring: false,\r
1089\r
1090 /**\r
1091 * @property {Boolean} isFirstInstance\r
1092 * This property is set to `true` if this instance is the first of its class.\r
1093 * @protected\r
1094 * @readonly\r
1095 * @since 5.0.0\r
1096 */\r
1097 isFirstInstance: false,\r
1098\r
1099 /**\r
1100 * @property {Boolean} destroyed\r
1101 * This property is set to `true` after the `destroy` method is called.\r
1102 * @protected\r
1103 */\r
1104 destroyed: false,\r
1105\r
1106 /**\r
1107 * Get the reference to the class from which this object was instantiated. Note that unlike {@link Ext.Base#self},\r
1108 * `this.statics()` is scope-independent and it always returns the class from which it was called, regardless of what\r
1109 * `this` points to during run-time\r
1110 *\r
1111 * Ext.define('My.Cat', {\r
1112 * statics: {\r
1113 * totalCreated: 0,\r
1114 * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'\r
1115 * },\r
1116 *\r
1117 * constructor: function() {\r
1118 * var statics = this.statics();\r
1119 *\r
1120 * alert(statics.speciesName); // always equals to 'Cat' no matter what 'this' refers to\r
1121 * // equivalent to: My.Cat.speciesName\r
1122 *\r
1123 * alert(this.self.speciesName); // dependent on 'this'\r
1124 *\r
1125 * statics.totalCreated++;\r
1126 * },\r
1127 *\r
1128 * clone: function() {\r
1129 * var cloned = new this.self(); // dependent on 'this'\r
1130 *\r
1131 * cloned.groupName = this.statics().speciesName; // equivalent to: My.Cat.speciesName\r
1132 *\r
1133 * return cloned;\r
1134 * }\r
1135 * });\r
1136 *\r
1137 *\r
1138 * Ext.define('My.SnowLeopard', {\r
1139 * extend: 'My.Cat',\r
1140 *\r
1141 * statics: {\r
1142 * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'\r
1143 * },\r
1144 *\r
1145 * constructor: function() {\r
1146 * this.callParent();\r
1147 * }\r
1148 * });\r
1149 *\r
1150 * var cat = new My.Cat(); // alerts 'Cat', then alerts 'Cat'\r
1151 *\r
1152 * var snowLeopard = new My.SnowLeopard(); // alerts 'Cat', then alerts 'Snow Leopard'\r
1153 *\r
1154 * var clone = snowLeopard.clone();\r
1155 * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'\r
1156 * alert(clone.groupName); // alerts 'Cat'\r
1157 *\r
1158 * alert(My.Cat.totalCreated); // alerts 3\r
1159 *\r
1160 * @protected\r
1161 * @return {Ext.Class}\r
1162 */\r
1163 statics: function() {\r
1164 var method = this.statics.caller,\r
1165 self = this.self;\r
1166\r
1167 if (!method) {\r
1168 return self;\r
1169 }\r
1170\r
1171 return method.$owner;\r
1172 },\r
1173\r
1174 /**\r
1175 * Call the "parent" method of the current method. That is the method previously\r
1176 * overridden by derivation or by an override (see {@link Ext#define}).\r
1177 *\r
1178 * Ext.define('My.Base', {\r
1179 * constructor: function (x) {\r
1180 * this.x = x;\r
1181 * },\r
1182 *\r
1183 * statics: {\r
1184 * method: function (x) {\r
1185 * return x;\r
1186 * }\r
1187 * }\r
1188 * });\r
1189 *\r
1190 * Ext.define('My.Derived', {\r
1191 * extend: 'My.Base',\r
1192 *\r
1193 * constructor: function () {\r
1194 * this.callParent([21]);\r
1195 * }\r
1196 * });\r
1197 *\r
1198 * var obj = new My.Derived();\r
1199 *\r
1200 * alert(obj.x); // alerts 21\r
1201 *\r
1202 * This can be used with an override as follows:\r
1203 *\r
1204 * Ext.define('My.DerivedOverride', {\r
1205 * override: 'My.Derived',\r
1206 *\r
1207 * constructor: function (x) {\r
1208 * this.callParent([x*2]); // calls original My.Derived constructor\r
1209 * }\r
1210 * });\r
1211 *\r
1212 * var obj = new My.Derived();\r
1213 *\r
1214 * alert(obj.x); // now alerts 42\r
1215 *\r
1216 * This also works with static and private methods.\r
1217 *\r
1218 * Ext.define('My.Derived2', {\r
1219 * extend: 'My.Base',\r
1220 *\r
1221 * // privates: {\r
1222 * statics: {\r
1223 * method: function (x) {\r
1224 * return this.callParent([x*2]); // calls My.Base.method\r
1225 * }\r
1226 * }\r
1227 * });\r
1228 *\r
1229 * alert(My.Base.method(10)); // alerts 10\r
1230 * alert(My.Derived2.method(10)); // alerts 20\r
1231 *\r
1232 * Lastly, it also works with overridden static methods.\r
1233 *\r
1234 * Ext.define('My.Derived2Override', {\r
1235 * override: 'My.Derived2',\r
1236 *\r
1237 * // privates: {\r
1238 * statics: {\r
1239 * method: function (x) {\r
1240 * return this.callParent([x*2]); // calls My.Derived2.method\r
1241 * }\r
1242 * }\r
1243 * });\r
1244 *\r
1245 * alert(My.Derived2.method(10); // now alerts 40\r
1246 *\r
1247 * To override a method and replace it and also call the superclass method, use\r
1248 * {@link #method-callSuper}. This is often done to patch a method to fix a bug.\r
1249 *\r
1250 * @protected\r
1251 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object\r
1252 * from the current method, for example: `this.callParent(arguments)`\r
1253 * @return {Object} Returns the result of calling the parent method\r
1254 */\r
1255 callParent: function(args) {\r
1256 // NOTE: this code is deliberately as few expressions (and no function calls)\r
1257 // as possible so that a debugger can skip over this noise with the minimum number\r
1258 // of steps. Basically, just hit Step Into until you are where you really wanted\r
1259 // to be.\r
1260 var method,\r
1261 superMethod = (method = this.callParent.caller) && (method.$previous ||\r
1262 ((method = method.$owner ? method : method.caller) &&\r
1263 method.$owner.superclass[method.$name]));\r
1264\r
1265 //<debug>\r
1266 if (!superMethod) {\r
1267 method = this.callParent.caller;\r
1268 var parentClass, methodName;\r
1269\r
1270 if (!method.$owner) {\r
1271 if (!method.caller) {\r
1272 throw new Error("Attempting to call a protected method from the public scope, which is not allowed");\r
1273 }\r
1274\r
1275 method = method.caller;\r
1276 }\r
1277\r
1278 parentClass = method.$owner.superclass;\r
1279 methodName = method.$name;\r
1280\r
1281 if (!(methodName in parentClass)) {\r
1282 throw new Error("this.callParent() was called but there's no such method (" + methodName +\r
1283 ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");\r
1284 }\r
1285 }\r
1286 //</debug>\r
1287\r
1288 return superMethod.apply(this, args || noArgs);\r
1289 },\r
1290\r
1291 /**\r
1292 * This method is used by an **override** to call the superclass method but \r
1293 * bypass any overridden method. This is often done to "patch" a method that \r
1294 * contains a bug but for whatever reason cannot be fixed directly.\r
1295 * \r
1296 * Consider:\r
1297 * \r
1298 * Ext.define('Ext.some.Class', {\r
1299 * method: function () {\r
1300 * console.log('Good');\r
1301 * }\r
1302 * });\r
1303 * \r
1304 * Ext.define('Ext.some.DerivedClass', {\r
1305 * extend: 'Ext.some.Class',\r
1306 * \r
1307 * method: function () {\r
1308 * console.log('Bad');\r
1309 * \r
1310 * // ... logic but with a bug ...\r
1311 * \r
1312 * this.callParent();\r
1313 * }\r
1314 * });\r
1315 * \r
1316 * To patch the bug in `Ext.some.DerivedClass.method`, the typical solution is to create an\r
1317 * override:\r
1318 * \r
1319 * Ext.define('App.patches.DerivedClass', {\r
1320 * override: 'Ext.some.DerivedClass',\r
1321 * \r
1322 * method: function () {\r
1323 * console.log('Fixed');\r
1324 * \r
1325 * // ... logic but with bug fixed ...\r
1326 *\r
1327 * this.callSuper();\r
1328 * }\r
1329 * });\r
1330 * \r
1331 * The patch method cannot use {@link #method-callParent} to call the superclass \r
1332 * `method` since that would call the overridden method containing the bug. In \r
1333 * other words, the above patch would only produce "Fixed" then "Good" in the \r
1334 * console log, whereas, using `callParent` would produce "Fixed" then "Bad" \r
1335 * then "Good".\r
1336 *\r
1337 * @protected\r
1338 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object\r
1339 * from the current method, for example: `this.callSuper(arguments)`\r
1340 * @return {Object} Returns the result of calling the superclass method\r
1341 */\r
1342 callSuper: function(args) {\r
1343 // NOTE: this code is deliberately as few expressions (and no function calls)\r
1344 // as possible so that a debugger can skip over this noise with the minimum number\r
1345 // of steps. Basically, just hit Step Into until you are where you really wanted\r
1346 // to be.\r
1347 var method,\r
1348 superMethod = (method = this.callSuper.caller) &&\r
1349 ((method = method.$owner ? method : method.caller) &&\r
1350 method.$owner.superclass[method.$name]);\r
1351\r
1352 //<debug>\r
1353 if (!superMethod) {\r
1354 method = this.callSuper.caller;\r
1355 var parentClass, methodName;\r
1356\r
1357 if (!method.$owner) {\r
1358 if (!method.caller) {\r
1359 throw new Error("Attempting to call a protected method from the public scope, which is not allowed");\r
1360 }\r
1361\r
1362 method = method.caller;\r
1363 }\r
1364\r
1365 parentClass = method.$owner.superclass;\r
1366 methodName = method.$name;\r
1367\r
1368 if (!(methodName in parentClass)) {\r
1369 throw new Error("this.callSuper() was called but there's no such method (" + methodName +\r
1370 ") found in the parent class (" + (Ext.getClassName(parentClass) || 'Object') + ")");\r
1371 }\r
1372 }\r
1373 //</debug>\r
1374\r
1375 return superMethod.apply(this, args || noArgs);\r
1376 },\r
1377\r
1378 /**\r
1379 * @property {Ext.Class} self\r
1380 *\r
1381 * Get the reference to the current class from which this object was instantiated. Unlike {@link Ext.Base#statics},\r
1382 * `this.self` is scope-dependent and it's meant to be used for dynamic inheritance. See {@link Ext.Base#statics}\r
1383 * for a detailed comparison\r
1384 *\r
1385 * Ext.define('My.Cat', {\r
1386 * statics: {\r
1387 * speciesName: 'Cat' // My.Cat.speciesName = 'Cat'\r
1388 * },\r
1389 *\r
1390 * constructor: function() {\r
1391 * alert(this.self.speciesName); // dependent on 'this'\r
1392 * },\r
1393 *\r
1394 * clone: function() {\r
1395 * return new this.self();\r
1396 * }\r
1397 * });\r
1398 *\r
1399 *\r
1400 * Ext.define('My.SnowLeopard', {\r
1401 * extend: 'My.Cat',\r
1402 * statics: {\r
1403 * speciesName: 'Snow Leopard' // My.SnowLeopard.speciesName = 'Snow Leopard'\r
1404 * }\r
1405 * });\r
1406 *\r
1407 * var cat = new My.Cat(); // alerts 'Cat'\r
1408 * var snowLeopard = new My.SnowLeopard(); // alerts 'Snow Leopard'\r
1409 *\r
1410 * var clone = snowLeopard.clone();\r
1411 * alert(Ext.getClassName(clone)); // alerts 'My.SnowLeopard'\r
1412 *\r
1413 * @protected\r
1414 */\r
1415 self: Base,\r
1416\r
1417 // Default constructor, simply returns `this`\r
1418 constructor: function() {\r
1419 return this;\r
1420 },\r
1421\r
1422 //<feature classSystem.config>\r
1423 getConfigurator: function () {\r
1424 return this.$config || this.self.getConfigurator();\r
1425 },\r
1426\r
1427 /**\r
1428 * Initialize configuration for this class. a typical example:\r
1429 *\r
1430 * Ext.define('My.awesome.Class', {\r
1431 * // The default config\r
1432 * config: {\r
1433 * name: 'Awesome',\r
1434 * isAwesome: true\r
1435 * },\r
1436 *\r
1437 * constructor: function(config) {\r
1438 * this.initConfig(config);\r
1439 * }\r
1440 * });\r
1441 *\r
1442 * var awesome = new My.awesome.Class({\r
1443 * name: 'Super Awesome'\r
1444 * });\r
1445 *\r
1446 * alert(awesome.getName()); // 'Super Awesome'\r
1447 *\r
1448 * @protected\r
1449 * @param {Object} config\r
1450 * @return {Ext.Base} this\r
1451 */\r
1452 initConfig: function(instanceConfig) {\r
1453 var me = this,\r
1454 cfg = me.getConfigurator();\r
1455\r
1456 me.initConfig = Ext.emptyFn; // ignore subsequent calls to initConfig\r
1457 me.initialConfig = instanceConfig || {};\r
1458 cfg.configure(me, instanceConfig);\r
1459\r
1460 return me;\r
1461 },\r
1462\r
1463 beforeInitConfig: Ext.emptyFn,\r
1464\r
1465 /**\r
1466 * Returns a specified config property value. If the name parameter is not passed,\r
1467 * all current configuration options will be returned as key value pairs.\r
1468 * @method\r
1469 * @param {String} [name] The name of the config property to get.\r
1470 * @param {Boolean} [peek=false] `true` to peek at the raw value without calling the getter.\r
1471 * @return {Object} The config property value.\r
1472 */\r
1473 getConfig: getConfig,\r
1474\r
1475 /**\r
1476 * Sets a single/multiple configuration options.\r
1477 * @method\r
1478 * @param {String/Object} name The name of the property to set, or a set of key value pairs to set.\r
1479 * @param {Object} [value] The value to set for the name parameter.\r
1480 * @return {Ext.Base} this\r
1481 */\r
1482 setConfig: function(name, value, /* private */ options) {\r
1483 // options can have the following properties:\r
1484 // - defaults `true` to only set the config(s) that have not been already set on\r
1485 // this instance.\r
1486 // - strict `false` to apply properties to the instance that are not configs,\r
1487 // and do not have setters.\r
1488 var me = this,\r
1489 config;\r
1490\r
1491 if (name) {\r
1492 if (typeof name === 'string') {\r
1493 config = {};\r
1494 config[name] = value;\r
1495 } else {\r
1496 config = name;\r
1497 }\r
1498\r
1499 me.getConfigurator().reconfigure(me, config, options);\r
1500 }\r
1501\r
1502 return me;\r
1503 },\r
1504\r
1505 /**\r
1506 * @private\r
1507 */\r
1508 getCurrentConfig: function() {\r
1509 var cfg = this.getConfigurator();\r
1510\r
1511 return cfg.getCurrentConfig(this);\r
1512 },\r
1513\r
1514 /**\r
1515 * @private\r
1516 * @param config\r
1517 */\r
1518 hasConfig: function(name) {\r
1519 return name in this.defaultConfig;\r
1520 },\r
1521\r
1522 /**\r
1523 * Returns the initial configuration passed to the constructor when \r
1524 * instantiating this class.\r
1525 * \r
1526 * Given this example Ext.button.Button definition and instance:\r
1527 * \r
1528 * Ext.define('MyApp.view.Button', {\r
1529 * extend: 'Ext.button.Button',\r
1530 * xtype: 'mybutton',\r
1531 * \r
1532 * scale: 'large',\r
1533 * enableToggle: true\r
1534 * });\r
1535 * \r
1536 * var btn = Ext.create({\r
1537 * xtype: 'mybutton',\r
1538 * renderTo: Ext.getBody(),\r
1539 * text: 'Test Button'\r
1540 * });\r
1541 * \r
1542 * Calling `btn.getInitialConfig()` would return an object including the config \r
1543 * options passed to the `create` method:\r
1544 * \r
1545 * xtype: 'mybutton',\r
1546 * renderTo: // The document body itself\r
1547 * text: 'Test Button'\r
1548 * \r
1549 * Calling `btn.getInitialConfig('text')`returns **'Test Button'**.\r
1550 * \r
1551 * @param {String} [name] Name of the config option to return.\r
1552 * @return {Object/Mixed} The full config object or a single config value\r
1553 * when `name` parameter specified.\r
1554 */\r
1555 getInitialConfig: function(name) {\r
1556 var config = this.config;\r
1557\r
1558 if (!name) {\r
1559 return config;\r
1560 }\r
1561\r
1562 return config[name];\r
1563 },\r
1564 //</feature>\r
1565\r
1566 $links: null,\r
1567\r
1568 /**\r
1569 * Adds a "destroyable" object to an internal list of objects that will be destroyed\r
1570 * when this instance is destroyed (via `{@link #destroy}`).\r
1571 * @param {String} name\r
1572 * @param {Object} value\r
1573 * @return {Object} The `value` passed.\r
1574 * @private\r
1575 */\r
1576 link: function (name, value) {\r
1577 var me = this,\r
1578 links = me.$links || (me.$links = {});\r
1579\r
1580 links[name] = true;\r
1581 me[name] = value;\r
1582\r
1583 return value;\r
1584 },\r
1585\r
1586 /**\r
1587 * Destroys a given set of `{@link #link linked}` objects. This is only needed if\r
1588 * the linked object is being destroyed before this instance.\r
1589 * @param {String[]} names The names of the linked objects to destroy.\r
1590 * @return {Ext.Base} this\r
1591 * @private\r
1592 */\r
1593 unlink: function (names) {\r
1594 var me = this,\r
1595 i, ln, link, value;\r
1596\r
1597 //<debug>\r
1598 if (!Ext.isArray(names)) {\r
1599 Ext.raise('Invalid argument - expected array of strings');\r
1600 }\r
1601 //</debug>\r
1602\r
1603 for (i = 0, ln = names.length; i < ln; i++) {\r
1604 link = names[i];\r
1605 value = me[link];\r
1606\r
1607 if (value) {\r
1608 if (value.isInstance && !value.destroyed) {\r
1609 value.destroy();\r
1610 }\r
1611 else if (value.parentNode && 'nodeType' in value) {\r
1612 value.parentNode.removeChild(value);\r
1613 }\r
1614 }\r
1615\r
1616 me[link] = null;\r
1617 }\r
1618\r
1619 return me;\r
1620 },\r
1621\r
1622 /**\r
1623 * This method is called to cleanup an object and its resources. After calling\r
1624 * this method, the object should not be used any further.\r
1625 */\r
1626 destroy: function() {\r
1627 var me = this,\r
1628 links = me.$links;\r
1629 \r
1630 me.initialConfig = me.config = null;\r
1631 \r
1632 me.destroy = Ext.emptyFn;\r
1633 // isDestroyed added for compat reasons\r
1634 me.isDestroyed = me.destroyed = true;\r
1635\r
1636 if (links) {\r
1637 me.$links = null;\r
1638 me.unlink(Ext.Object.getKeys(links));\r
1639 }\r
1640 }\r
1641 });\r
1642\r
1643 /**\r
1644 * Call the original method that was previously overridden with {@link Ext.Base#override}\r
1645 *\r
1646 * Ext.define('My.Cat', {\r
1647 * constructor: function() {\r
1648 * alert("I'm a cat!");\r
1649 * }\r
1650 * });\r
1651 *\r
1652 * My.Cat.override({\r
1653 * constructor: function() {\r
1654 * alert("I'm going to be a cat!");\r
1655 *\r
1656 * this.callOverridden();\r
1657 *\r
1658 * alert("Meeeeoooowwww");\r
1659 * }\r
1660 * });\r
1661 *\r
1662 * var kitty = new My.Cat(); // alerts "I'm going to be a cat!"\r
1663 * // alerts "I'm a cat!"\r
1664 * // alerts "Meeeeoooowwww"\r
1665 *\r
1666 * @param {Array/Arguments} args The arguments, either an array or the `arguments` object\r
1667 * from the current method, for example: `this.callOverridden(arguments)`\r
1668 * @return {Object} Returns the result of calling the overridden method\r
1669 * @protected\r
1670 * @deprecated Use {@link #callParent} instead.\r
1671 */\r
1672 BasePrototype.callOverridden = BasePrototype.callParent;\r
1673\r
1674 //<debug>\r
1675 Ext.privacyViolation = function (cls, existing, member, isStatic) {\r
1676 var name = member.$name,\r
1677 conflictCls = existing.$owner && existing.$owner.$className,\r
1678 s = isStatic ? 'static ' : '',\r
1679 msg = member.$privacy\r
1680 ? 'Private ' + s + member.$privacy + ' method "' + name + '"'\r
1681 : 'Public ' + s + 'method "' + name + '"';\r
1682\r
1683 if (cls.$className) {\r
1684 msg = cls.$className + ': ' + msg;\r
1685 }\r
1686\r
1687 if (!existing.$privacy) {\r
1688 msg += conflictCls\r
1689 ? ' hides public method inherited from ' + conflictCls\r
1690 : ' hides inherited public method.';\r
1691 } else {\r
1692 msg += conflictCls\r
1693 ? ' conflicts with private ' + existing.$privacy +\r
1694 ' method declared by ' + conflictCls\r
1695 : ' conflicts with inherited private ' + existing.$privacy + ' method.';\r
1696 }\r
1697\r
1698 var compat = Ext.getCompatVersion();\r
1699 var ver = Ext.getVersion();\r
1700\r
1701 // When compatibility is enabled, log problems instead of throwing errors.\r
1702 if (ver && compat && compat.lt(ver)) {\r
1703 Ext.log.error(msg);\r
1704 } else {\r
1705 Ext.raise(msg);\r
1706 }\r
1707 };\r
1708 //</debug>\r
1709\r
1710 return Base;\r
1711}(Ext.Function.flexSetter));\r