]>
Commit | Line | Data |
---|---|---|
6527f429 DM |
1 | // @tag core\r |
2 | /**\r | |
3 | * @class Ext\r | |
4 | *\r | |
5 | * The Ext namespace (global object) encapsulates all classes, singletons, and\r | |
6 | * utility methods provided by Sencha's libraries.\r | |
7 | *\r | |
8 | * Most user interface Components are at a lower level of nesting in the namespace,\r | |
9 | * but many common utility functions are provided as direct properties of the Ext namespace.\r | |
10 | *\r | |
11 | * Also many frequently used methods from other classes are provided as shortcuts\r | |
12 | * within the Ext namespace. For example {@link Ext#getCmp Ext.getCmp} aliases\r | |
13 | * {@link Ext.ComponentManager#get Ext.ComponentManager.get}.\r | |
14 | *\r | |
15 | * Many applications are initiated with {@link Ext#application Ext.application} which is\r | |
16 | * called once the DOM is ready. This ensures all scripts have been loaded, preventing\r | |
17 | * dependency issues. For example:\r | |
18 | *\r | |
19 | * Ext.application({\r | |
20 | * name: 'MyApp',\r | |
21 | *\r | |
22 | * launch: function () {\r | |
23 | * Ext.Msg.alert(this.name, 'Ready to go!');\r | |
24 | * }\r | |
25 | * });\r | |
26 | *\r | |
27 | * <b><a href="http://www.sencha.com/products/sencha-cmd/">Sencha Cmd</a></b> is a free tool\r | |
28 | * for helping you generate and build Ext JS (and Sencha Touch) applications. See\r | |
29 | * `{@link Ext.app.Application Application}` for more information about creating an app.\r | |
30 | *\r | |
31 | * A lower-level technique that does not use the `Ext.app.Application` architecture is\r | |
32 | * {@link Ext#onReady Ext.onReady}.\r | |
33 | *\r | |
34 | * For more information about how to use the Ext classes, see:\r | |
35 | *\r | |
36 | * - <a href="http://www.sencha.com/learn/">The Learning Center</a>\r | |
37 | * - <a href="http://www.sencha.com/learn/Ext_FAQ">The FAQ</a>\r | |
38 | * - <a href="http://www.sencha.com/forum/">The forums</a>\r | |
39 | *\r | |
40 | * @singleton\r | |
41 | */\r | |
42 | var Ext = Ext || {}; // jshint ignore:line\r | |
43 | // @define Ext\r | |
44 | \r | |
45 | (function() {\r | |
46 | var global = this,\r | |
47 | objectPrototype = Object.prototype,\r | |
48 | toString = objectPrototype.toString,\r | |
49 | enumerables = [//'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\r | |
50 | 'valueOf', 'toLocaleString', 'toString', 'constructor'],\r | |
51 | emptyFn = function () {},\r | |
52 | privateFn = function () {},\r | |
53 | identityFn = function(o) { return o; },\r | |
54 | // This is the "$previous" method of a hook function on an instance. When called, it\r | |
55 | // calls through the class prototype by the name of the called method.\r | |
56 | callOverrideParent = function () {\r | |
57 | var method = callOverrideParent.caller.caller; // skip callParent (our caller)\r | |
58 | return method.$owner.prototype[method.$name].apply(this, arguments);\r | |
59 | },\r | |
60 | manifest = Ext.manifest || {},\r | |
61 | i,\r | |
62 | iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|HTML\s+document\.all\s+class)\]/,\r | |
63 | MSDateRe = /^\\?\/Date\(([-+])?(\d+)(?:[+-]\d{4})?\)\\?\/$/;\r | |
64 | \r | |
65 | Ext.global = global;\r | |
66 | \r | |
67 | /**\r | |
68 | * Returns the current timestamp.\r | |
69 | * @return {Number} Milliseconds since UNIX epoch.\r | |
70 | * @method now\r | |
71 | * @member Ext\r | |
72 | */\r | |
73 | Ext.now = Date.now || (Date.now = function() {\r | |
74 | return +new Date();\r | |
75 | });\r | |
76 | \r | |
77 | /**\r | |
78 | * Returns the current high-resolution timestamp.\r | |
79 | * @return {Number} Milliseconds ellapsed since arbitrary epoch.\r | |
80 | * @method ticks\r | |
81 | * @member Ext\r | |
82 | * @since 6.0.1\r | |
83 | */\r | |
84 | Ext.ticks = (global.performance && global.performance.now) ? function() {\r | |
85 | return performance.now(); // jshint ignore:line\r | |
86 | } : Ext.now;\r | |
87 | \r | |
88 | Ext._startTime = Ext.ticks();\r | |
89 | \r | |
90 | // Mark these special fn's for easy identification:\r | |
91 | emptyFn.$nullFn = identityFn.$nullFn = emptyFn.$emptyFn = identityFn.$identityFn =\r | |
92 | privateFn.$nullFn = true;\r | |
93 | privateFn.$privacy = 'framework';\r | |
94 | \r | |
95 | // These are emptyFn's in core and are redefined only in Ext JS (we use this syntax\r | |
96 | // so Cmd does not detect them):\r | |
97 | Ext['suspendLayouts'] = Ext['resumeLayouts'] = emptyFn; // jshint ignore:line\r | |
98 | \r | |
99 | for (i in { toString: 1 }) {\r | |
100 | enumerables = null;\r | |
101 | }\r | |
102 | \r | |
103 | /**\r | |
104 | * An array containing extra enumerables for old browsers\r | |
105 | * @property {String[]}\r | |
106 | */\r | |
107 | Ext.enumerables = enumerables;\r | |
108 | \r | |
109 | /**\r | |
110 | * Copies all the properties of `config` to the specified `object`. There are two levels\r | |
111 | * of defaulting supported:\r | |
112 | * \r | |
113 | * Ext.apply(obj, { a: 1 }, { a: 2 });\r | |
114 | * //obj.a === 1\r | |
115 | * \r | |
116 | * Ext.apply(obj, { }, { a: 2 });\r | |
117 | * //obj.a === 2\r | |
118 | * \r | |
119 | * Note that if recursive merging and cloning without referencing the original objects\r | |
120 | * or arrays is needed, use {@link Ext.Object#merge} instead.\r | |
121 | * \r | |
122 | * @param {Object} object The receiver of the properties.\r | |
123 | * @param {Object} config The primary source of the properties.\r | |
124 | * @param {Object} [defaults] An object that will also be applied for default values.\r | |
125 | * @return {Object} returns `object`.\r | |
126 | */\r | |
127 | Ext.apply = function(object, config, defaults) {\r | |
128 | if (defaults) {\r | |
129 | Ext.apply(object, defaults);\r | |
130 | }\r | |
131 | \r | |
132 | if (object && config && typeof config === 'object') {\r | |
133 | var i, j, k;\r | |
134 | \r | |
135 | for (i in config) {\r | |
136 | object[i] = config[i];\r | |
137 | }\r | |
138 | \r | |
139 | if (enumerables) {\r | |
140 | for (j = enumerables.length; j--;) {\r | |
141 | k = enumerables[j];\r | |
142 | if (config.hasOwnProperty(k)) {\r | |
143 | object[k] = config[k];\r | |
144 | }\r | |
145 | }\r | |
146 | }\r | |
147 | }\r | |
148 | \r | |
149 | return object;\r | |
150 | };\r | |
151 | \r | |
152 | // Used by Ext.override\r | |
153 | function addInstanceOverrides(target, owner, overrides) {\r | |
154 | var name, value;\r | |
155 | \r | |
156 | for (name in overrides) {\r | |
157 | if (overrides.hasOwnProperty(name)) {\r | |
158 | value = overrides[name];\r | |
159 | \r | |
160 | if (typeof value === 'function') {\r | |
161 | //<debug>\r | |
162 | if (owner.$className) {\r | |
163 | value.name = owner.$className + '#' + name;\r | |
164 | }\r | |
165 | //</debug>\r | |
166 | \r | |
167 | value.$name = name;\r | |
168 | value.$owner = owner;\r | |
169 | \r | |
170 | value.$previous = target.hasOwnProperty(name) ?\r | |
171 | target[name] // already hooked, so call previous hook\r | |
172 | : callOverrideParent; // calls by name on prototype\r | |
173 | }\r | |
174 | \r | |
175 | target[name] = value;\r | |
176 | }\r | |
177 | }\r | |
178 | }\r | |
179 | \r | |
180 | Ext.buildSettings = Ext.apply({\r | |
181 | baseCSSPrefix: 'x-'\r | |
182 | }, Ext.buildSettings || {});\r | |
183 | \r | |
184 | Ext.apply(Ext, {\r | |
185 | /**\r | |
186 | * @private\r | |
187 | */\r | |
188 | idSeed: 0,\r | |
189 | \r | |
190 | /**\r | |
191 | * @private\r | |
192 | */\r | |
193 | idPrefix: 'ext-',\r | |
194 | \r | |
195 | /**\r | |
196 | * @property {Boolean} isSecure\r | |
197 | * True if the page is running over SSL\r | |
198 | * @readonly\r | |
199 | */\r | |
200 | isSecure: /^https/i.test(window.location.protocol),\r | |
201 | \r | |
202 | /**\r | |
203 | * `true` to automatically uncache orphaned Ext.Elements periodically. If set to\r | |
204 | * `false`, the application will be required to clean up orphaned Ext.Elements and\r | |
205 | * it's listeners as to not cause memory leakage.\r | |
206 | */\r | |
207 | enableGarbageCollector: false,\r | |
208 | \r | |
209 | /**\r | |
210 | * True to automatically purge event listeners during garbageCollection.\r | |
211 | */\r | |
212 | enableListenerCollection: true,\r | |
213 | \r | |
214 | /**\r | |
215 | * @property {String} [name='Ext']\r | |
216 | * <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>\r | |
217 | * <p>This is usually <code>"Ext"</code>, but if a sandboxed build of ExtJS is being used, this will be an alternative name.</p>\r | |
218 | * <p>If code is being generated for use by <code>eval</code> or to create a <code>new Function</code>, and the global instance\r | |
219 | * of Ext must be referenced, this is the name that should be built into the code.</p>\r | |
220 | */\r | |
221 | name: Ext.sandboxName || 'Ext',\r | |
222 | \r | |
223 | /**\r | |
224 | * @property {Function}\r | |
225 | * A reusable empty function for use as `privates` members.\r | |
226 | *\r | |
227 | * Ext.define('MyClass', {\r | |
228 | * nothing: Ext.emptyFn,\r | |
229 | *\r | |
230 | * privates: {\r | |
231 | * privateNothing: Ext.privateFn\r | |
232 | * }\r | |
233 | * });\r | |
234 | *\r | |
235 | */\r | |
236 | privateFn: privateFn,\r | |
237 | \r | |
238 | /**\r | |
239 | * @property {Function}\r | |
240 | * A reusable empty function.\r | |
241 | */\r | |
242 | emptyFn: emptyFn,\r | |
243 | \r | |
244 | /**\r | |
245 | * @property {Function}\r | |
246 | * A reusable identity function that simply returns its first argument.\r | |
247 | */\r | |
248 | identityFn: identityFn,\r | |
249 | \r | |
250 | /**\r | |
251 | * This indicate the start timestamp of current cycle.\r | |
252 | * It is only reliable during dom-event-initiated cycles and\r | |
253 | * {@link Ext.draw.Animator} initiated cycles.\r | |
254 | */\r | |
255 | frameStartTime: Ext.now(),\r | |
256 | \r | |
257 | /**\r | |
258 | * This object is initialized prior to loading the framework (Ext JS or Sencha\r | |
259 | * Touch) and contains settings and other information describing the application.\r | |
260 | *\r | |
261 | * For applications built using Sencha Cmd, this is produced from the `"app.json"`\r | |
262 | * file with information extracted from all of the required packages' `"package.json"`\r | |
263 | * files. This can be set to a string when your application is using the\r | |
264 | * (microloader)[#/guide/microloader]. In this case, the string of "foo" will be\r | |
265 | * requested as `"foo.json"` and the object in that JSON file will parsed and set\r | |
266 | * as this object.\r | |
267 | *\r | |
268 | * @cfg {String/Object} manifest\r | |
269 | *\r | |
270 | * @cfg {String/Object} manifest.compatibility An object keyed by package name with\r | |
271 | * the value being to desired compatibility level as a version number. If this is\r | |
272 | * just a string, this version is assumed to apply to the framework ('ext' or\r | |
273 | * 'touch'). Setting this value to less than 5 for 'ext' will enable the compatibility\r | |
274 | * layer to assist in the application upgrade process. For details on the upgrade\r | |
275 | * process, see the (Upgrade Guide)[#/guides/upgrade_50].\r | |
276 | *\r | |
277 | * @cfg {Object} manifest.debug An object configuring the debugging characteristics\r | |
278 | * of the framework. See `Ext.debugConfig` which is set to this value.\r | |
279 | *\r | |
280 | * @cfg {Object} manifest.packages An object keyed by package name with the value\r | |
281 | * being a subset of the package's `"package.json"` descriptor.\r | |
282 | * @since 5.0.0\r | |
283 | */\r | |
284 | manifest: manifest,\r | |
285 | \r | |
286 | //<debug>\r | |
287 | /**\r | |
288 | * @cfg {Object} [debugConfig]\r | |
289 | * This object is used to enable or disable debugging for classes or namespaces. The\r | |
290 | * default instance looks like this:\r | |
291 | *\r | |
292 | * Ext.debugConfig = {\r | |
293 | * hooks: {\r | |
294 | * '*': true\r | |
295 | * }\r | |
296 | * };\r | |
297 | *\r | |
298 | * Typically applications will set this in their `"app.json"` like so:\r | |
299 | *\r | |
300 | * {\r | |
301 | * "debug": {\r | |
302 | * "hooks": {\r | |
303 | * // Default for all namespaces:\r | |
304 | * '*': true,\r | |
305 | *\r | |
306 | * // Except for Ext namespace which is disabled\r | |
307 | * 'Ext': false,\r | |
308 | *\r | |
309 | * // Except for Ext.layout namespace which is enabled\r | |
310 | * 'Ext.layout': true\r | |
311 | * }\r | |
312 | * }\r | |
313 | * }\r | |
314 | *\r | |
315 | * Alternatively, because this property is consumed very early in the load process of\r | |
316 | * the framework, this can be set in a `script` tag that is defined prior to loading\r | |
317 | * the framework itself.\r | |
318 | *\r | |
319 | * For example, to enable debugging for the `Ext.layout` namespace only:\r | |
320 | *\r | |
321 | * var Ext = Ext || {};\r | |
322 | * Ext.debugConfig = {\r | |
323 | * hooks: {\r | |
324 | * //...\r | |
325 | * }\r | |
326 | * };\r | |
327 | *\r | |
328 | * For any class declared, the longest matching namespace specified determines if its\r | |
329 | * `debugHooks` will be enabled. The default setting is specified by the '*' property.\r | |
330 | *\r | |
331 | * **NOTE:** This option only applies to debug builds. All debugging is disabled in\r | |
332 | * production builds.\r | |
333 | */\r | |
334 | debugConfig: Ext.debugConfig || manifest.debug || {\r | |
335 | hooks: {\r | |
336 | '*': true\r | |
337 | }\r | |
338 | },\r | |
339 | //</debug>\r | |
340 | \r | |
341 | /**\r | |
342 | * @property {Boolean} [enableAria=true] This property is provided for backward\r | |
343 | * compatibility with previous versions of Ext JS. Accessibility is always enabled\r | |
344 | * in Ext JS 6.0+\r | |
345 | * @since 6.0.0\r | |
346 | */\r | |
347 | enableAria: true,\r | |
348 | \r | |
349 | /**\r | |
350 | * @property {Boolean} [enableAriaButtons=true] Set to `false` to disable WAI-ARIA\r | |
351 | * compatibility checks for buttons.\r | |
352 | * @since 6.0.0\r | |
353 | */\r | |
354 | enableAriaButtons: true,\r | |
355 | \r | |
356 | /**\r | |
357 | * @property {Boolean} [enableAriaPanels=true] Set to `false` to disable WAI-ARIA\r | |
358 | * compatibility checks for panels.\r | |
359 | * @since 6.0.0\r | |
360 | */\r | |
361 | enableAriaPanels: true,\r | |
362 | \r | |
363 | startsWithHashRe: /^#/,\r | |
364 | \r | |
365 | /**\r | |
366 | * @property {RegExp}\r | |
367 | * @private\r | |
368 | * Regular expression used for validating identifiers.\r | |
369 | */\r | |
370 | validIdRe: /^[a-z_][a-z0-9\-_]*$/i,\r | |
371 | \r | |
372 | /**\r | |
373 | * @property {String} BLANK_IMAGE_URL\r | |
374 | * URL to a 1x1 transparent gif image used by Ext to create inline icons with\r | |
375 | * CSS background images.\r | |
376 | */\r | |
377 | BLANK_IMAGE_URL: 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',\r | |
378 | \r | |
379 | /**\r | |
380 | * Converts an id (`'foo'`) into an id selector (`'#foo'`). This method is used\r | |
381 | * internally by the framework whenever an id needs to be converted into a selector\r | |
382 | * and is provided as a hook for those that need to escape IDs selectors since,\r | |
383 | * as of Ext 5.0, the framework no longer escapes IDs by default.\r | |
384 | * @private\r | |
385 | * @param {String} id\r | |
386 | * @return {String}\r | |
387 | */\r | |
388 | makeIdSelector: function(id) {\r | |
389 | //<debug>\r | |
390 | if (!Ext.validIdRe.test(id)) {\r | |
391 | Ext.raise('Invalid id selector: "' + id + '"');\r | |
392 | }\r | |
393 | //</debug>\r | |
394 | return '#' + id;\r | |
395 | },\r | |
396 | \r | |
397 | /**\r | |
398 | * Generates unique ids. If the object/element is passes and it already has an `id`, it is unchanged.\r | |
399 | * @param {Object} [o] The object to generate an id for.\r | |
400 | * @param {String} [prefix=ext-gen] (optional) The `id` prefix.\r | |
401 | * @return {String} The generated `id`.\r | |
402 | */\r | |
403 | id: function(o, prefix) {\r | |
404 | if (o && o.id) {\r | |
405 | return o.id;\r | |
406 | }\r | |
407 | \r | |
408 | var id = (prefix || Ext.idPrefix) + (++Ext.idSeed);\r | |
409 | \r | |
410 | if (o) {\r | |
411 | o.id = id;\r | |
412 | }\r | |
413 | \r | |
414 | return id;\r | |
415 | },\r | |
416 | \r | |
417 | /**\r | |
418 | * A reusable function which returns the value of `getId()` called upon a single passed parameter.\r | |
419 | * Useful when creating a {@link Ext.util.MixedCollection} of objects keyed by an identifier returned from a `getId` method.\r | |
420 | */\r | |
421 | returnId: function(o) {\r | |
422 | return o.getId();\r | |
423 | },\r | |
424 | \r | |
425 | /**\r | |
426 | * A reusable function which returns `true`.\r | |
427 | */\r | |
428 | returnTrue: function() {\r | |
429 | return true;\r | |
430 | },\r | |
431 | \r | |
432 | /**\r | |
433 | * A zero length string which will pass a truth test. Useful for passing to methods\r | |
434 | * which use a truth test to reject <i>falsy</i> values where a string value must be cleared.\r | |
435 | */\r | |
436 | emptyString: new String(), // jshint ignore:line\r | |
437 | \r | |
438 | /**\r | |
439 | * @property {String} [baseCSSPrefix='x-']\r | |
440 | * The base prefix to use for all `Ext` components. To configure this property, you should use the\r | |
441 | * Ext.buildSettings object before the framework is loaded:\r | |
442 | *\r | |
443 | * Ext.buildSettings = {\r | |
444 | * baseCSSPrefix : 'abc-'\r | |
445 | * };\r | |
446 | *\r | |
447 | * or you can change it before any components are rendered:\r | |
448 | *\r | |
449 | * Ext.baseCSSPrefix = Ext.buildSettings.baseCSSPrefix = 'abc-';\r | |
450 | *\r | |
451 | * This will change what CSS classes components will use and you should\r | |
452 | * then recompile the SASS changing the `$prefix` SASS variable to match.\r | |
453 | */\r | |
454 | baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,\r | |
455 | \r | |
456 | /**\r | |
457 | * @property {Object} $eventNameMap\r | |
458 | * A map of event names which contained the lower-cased versions of any mixed\r | |
459 | * case event names.\r | |
460 | * @private\r | |
461 | */\r | |
462 | $eventNameMap: {},\r | |
463 | \r | |
464 | // Vendor-specific events do not work if lower-cased. This regex specifies event\r | |
465 | // prefixes for names that should NOT be lower-cased by Ext.canonicalEventName()\r | |
466 | $vendorEventRe: /^(Moz.+|MS.+|webkit.+)/,\r | |
467 | \r | |
468 | // TODO: inlinable function - SDKTOOLS-686\r | |
469 | /**\r | |
470 | * @private\r | |
471 | * @inline\r | |
472 | */\r | |
473 | canonicalEventName: function(name) {\r | |
474 | return Ext.$eventNameMap[name] || (Ext.$eventNameMap[name] =\r | |
475 | (Ext.$vendorEventRe.test(name) ? name : name.toLowerCase()));\r | |
476 | },\r | |
477 | \r | |
478 | /**\r | |
479 | * Copies all the properties of config to object if they don't already exist.\r | |
480 | * @param {Object} object The receiver of the properties\r | |
481 | * @param {Object} config The source of the properties\r | |
482 | * @return {Object} returns obj\r | |
483 | */\r | |
484 | applyIf: function(object, config) {\r | |
485 | var property;\r | |
486 | \r | |
487 | if (object) {\r | |
488 | for (property in config) {\r | |
489 | if (object[property] === undefined) {\r | |
490 | object[property] = config[property];\r | |
491 | }\r | |
492 | }\r | |
493 | }\r | |
494 | \r | |
495 | return object;\r | |
496 | },\r | |
497 | \r | |
498 | /**\r | |
499 | * Destroys all of the given objects. If arrays are passed, the elements of these\r | |
500 | * are destroyed recursively.\r | |
501 | *\r | |
502 | * What it means to "destroy" an object depends on the type of object.\r | |
503 | *\r | |
504 | * * `Array`: Each element of the array is destroyed recursively.\r | |
505 | * * `Object`: Any object with a `destroy` method will have that method called.\r | |
506 | *\r | |
507 | * @param {Mixed...} args Any number of objects or arrays.\r | |
508 | */\r | |
509 | destroy: function() {\r | |
510 | var ln = arguments.length,\r | |
511 | i, arg;\r | |
512 | \r | |
513 | for (i = 0; i < ln; i++) {\r | |
514 | arg = arguments[i];\r | |
515 | if (arg) {\r | |
516 | if (Ext.isArray(arg)) {\r | |
517 | this.destroy.apply(this, arg);\r | |
518 | } else if (Ext.isFunction(arg.destroy)) {\r | |
519 | arg.destroy();\r | |
520 | }\r | |
521 | }\r | |
522 | }\r | |
523 | return null;\r | |
524 | },\r | |
525 | \r | |
526 | /**\r | |
527 | * Destroys the specified named members of the given object using `Ext.destroy`. These\r | |
528 | * properties will be set to `null`.\r | |
529 | * @param {Object} object The object who's properties you wish to destroy.\r | |
530 | * @param {String...} args One or more names of the properties to destroy and remove from the object.\r | |
531 | */\r | |
532 | destroyMembers: function (object) {\r | |
533 | for (var ref, name, i = 1, a = arguments, len = a.length; i < len; i++) {\r | |
534 | ref = object[name = a[i]];\r | |
535 | \r | |
536 | // Avoid adding the property if it does not already exist\r | |
537 | if (ref != null) {\r | |
538 | object[name] = Ext.destroy(ref);\r | |
539 | }\r | |
540 | }\r | |
541 | },\r | |
542 | \r | |
543 | /**\r | |
544 | * Overrides members of the specified `target` with the given values.\r | |
545 | *\r | |
546 | * If the `target` is a class declared using {@link Ext#define Ext.define}, the\r | |
547 | * `override` method of that class is called (see {@link Ext.Base#override}) given\r | |
548 | * the `overrides`.\r | |
549 | *\r | |
550 | * If the `target` is a function, it is assumed to be a constructor and the contents\r | |
551 | * of `overrides` are applied to its `prototype` using {@link Ext#apply Ext.apply}.\r | |
552 | *\r | |
553 | * If the `target` is an instance of a class declared using {@link Ext#define Ext.define},\r | |
554 | * the `overrides` are applied to only that instance. In this case, methods are\r | |
555 | * specially processed to allow them to use {@link Ext.Base#callParent}.\r | |
556 | *\r | |
557 | * var panel = new Ext.Panel({ ... });\r | |
558 | *\r | |
559 | * Ext.override(panel, {\r | |
560 | * initComponent: function () {\r | |
561 | * // extra processing...\r | |
562 | *\r | |
563 | * this.callParent();\r | |
564 | * }\r | |
565 | * });\r | |
566 | *\r | |
567 | * If the `target` is none of these, the `overrides` are applied to the `target`\r | |
568 | * using {@link Ext#apply Ext.apply}.\r | |
569 | *\r | |
570 | * Please refer to {@link Ext#define Ext.define} and {@link Ext.Base#override} for\r | |
571 | * further details.\r | |
572 | *\r | |
573 | * @param {Object} target The target to override.\r | |
574 | * @param {Object} overrides The properties to add or replace on `target`.\r | |
575 | * @method override\r | |
576 | */\r | |
577 | override: function (target, overrides) {\r | |
578 | if (target.$isClass) {\r | |
579 | target.override(overrides);\r | |
580 | } else if (typeof target === 'function') {\r | |
581 | Ext.apply(target.prototype, overrides);\r | |
582 | } else {\r | |
583 | var owner = target.self,\r | |
584 | privates;\r | |
585 | \r | |
586 | if (owner && owner.$isClass) { // if (instance of Ext.define'd class)\r | |
587 | privates = overrides.privates;\r | |
588 | if (privates) {\r | |
589 | overrides = Ext.apply({}, overrides);\r | |
590 | delete overrides.privates;\r | |
591 | addInstanceOverrides(target, owner, privates);\r | |
592 | }\r | |
593 | \r | |
594 | addInstanceOverrides(target, owner, overrides);\r | |
595 | } else {\r | |
596 | Ext.apply(target, overrides);\r | |
597 | }\r | |
598 | }\r | |
599 | \r | |
600 | return target;\r | |
601 | },\r | |
602 | \r | |
603 | /**\r | |
604 | * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default\r | |
605 | * value (second argument) otherwise.\r | |
606 | *\r | |
607 | * @param {Object} value The value to test.\r | |
608 | * @param {Object} defaultValue The value to return if the original value is empty.\r | |
609 | * @param {Boolean} [allowBlank=false] `true` to allow zero length strings to qualify as non-empty.\r | |
610 | * @return {Object} value, if non-empty, else defaultValue.\r | |
611 | */\r | |
612 | valueFrom: function(value, defaultValue, allowBlank){\r | |
613 | return Ext.isEmpty(value, allowBlank) ? defaultValue : value;\r | |
614 | },\r | |
615 | \r | |
616 | /**\r | |
617 | * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if it is either:\r | |
618 | *\r | |
619 | * - `null`\r | |
620 | * - `undefined`\r | |
621 | * - a zero-length array\r | |
622 | * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`)\r | |
623 | *\r | |
624 | * @param {Object} value The value to test.\r | |
625 | * @param {Boolean} [allowEmptyString=false] `true` to allow empty strings.\r | |
626 | * @return {Boolean}\r | |
627 | */\r | |
628 | isEmpty: function(value, allowEmptyString) {\r | |
629 | return (value == null) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);\r | |
630 | },\r | |
631 | \r | |
632 | /**\r | |
633 | * Returns `true` if the passed value is a JavaScript Array, `false` otherwise.\r | |
634 | *\r | |
635 | * @param {Object} target The target to test.\r | |
636 | * @return {Boolean}\r | |
637 | * @method\r | |
638 | */\r | |
639 | isArray: ('isArray' in Array) ? Array.isArray : function(value) {\r | |
640 | return toString.call(value) === '[object Array]';\r | |
641 | },\r | |
642 | \r | |
643 | /**\r | |
644 | * Returns `true` if the passed value is a JavaScript Date object, `false` otherwise.\r | |
645 | * @param {Object} object The object to test.\r | |
646 | * @return {Boolean}\r | |
647 | */\r | |
648 | isDate: function(value) {\r | |
649 | return toString.call(value) === '[object Date]';\r | |
650 | },\r | |
651 | \r | |
652 | /**\r | |
653 | * Returns 'true' if the passed value is a String that matches the MS Date JSON\r | |
654 | * encoding format.\r | |
655 | * @param {String} value The string to test.\r | |
656 | * @return {Boolean}\r | |
657 | */\r | |
658 | isMSDate: function(value) {\r | |
659 | if (!Ext.isString(value)) {\r | |
660 | return false;\r | |
661 | }\r | |
662 | return MSDateRe.test(value);\r | |
663 | },\r | |
664 | \r | |
665 | /**\r | |
666 | * Returns `true` if the passed value is a JavaScript Object, `false` otherwise.\r | |
667 | * @param {Object} value The value to test.\r | |
668 | * @return {Boolean}\r | |
669 | * @method\r | |
670 | */\r | |
671 | isObject: (toString.call(null) === '[object Object]') ?\r | |
672 | function(value) {\r | |
673 | // check ownerDocument here as well to exclude DOM nodes\r | |
674 | return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;\r | |
675 | } :\r | |
676 | function(value) {\r | |
677 | return toString.call(value) === '[object Object]';\r | |
678 | },\r | |
679 | \r | |
680 | /**\r | |
681 | * @private\r | |
682 | */\r | |
683 | isSimpleObject: function(value) {\r | |
684 | return value instanceof Object && value.constructor === Object;\r | |
685 | },\r | |
686 | \r | |
687 | /**\r | |
688 | * Returns `true` if the passed value is a JavaScript 'primitive', a string, number\r | |
689 | * or boolean.\r | |
690 | * @param {Object} value The value to test.\r | |
691 | * @return {Boolean}\r | |
692 | */\r | |
693 | isPrimitive: function(value) {\r | |
694 | var type = typeof value;\r | |
695 | \r | |
696 | return type === 'string' || type === 'number' || type === 'boolean';\r | |
697 | },\r | |
698 | \r | |
699 | /**\r | |
700 | * Returns `true` if the passed value is a JavaScript Function, `false` otherwise.\r | |
701 | * @param {Object} value The value to test.\r | |
702 | * @return {Boolean}\r | |
703 | * @method\r | |
704 | */\r | |
705 | isFunction:\r | |
706 | // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using\r | |
707 | // Object.prototype.toString (slower)\r | |
708 | (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {\r | |
709 | return !!value && toString.call(value) === '[object Function]';\r | |
710 | } : function(value) {\r | |
711 | return !!value && typeof value === 'function';\r | |
712 | },\r | |
713 | \r | |
714 | /**\r | |
715 | * Returns `true` if the passed value is a number. Returns `false` for non-finite numbers.\r | |
716 | * @param {Object} value The value to test.\r | |
717 | * @return {Boolean}\r | |
718 | */\r | |
719 | isNumber: function(value) {\r | |
720 | return typeof value === 'number' && isFinite(value);\r | |
721 | },\r | |
722 | \r | |
723 | /**\r | |
724 | * Validates that a value is numeric.\r | |
725 | * @param {Object} value Examples: 1, '1', '2.34'\r | |
726 | * @return {Boolean} True if numeric, false otherwise\r | |
727 | */\r | |
728 | isNumeric: function(value) {\r | |
729 | return !isNaN(parseFloat(value)) && isFinite(value);\r | |
730 | },\r | |
731 | \r | |
732 | /**\r | |
733 | * Returns `true `if the passed value is a string.\r | |
734 | * @param {Object} value The value to test.\r | |
735 | * @return {Boolean}\r | |
736 | */\r | |
737 | isString: function(value) {\r | |
738 | return typeof value === 'string';\r | |
739 | },\r | |
740 | \r | |
741 | /**\r | |
742 | * Returns `true` if the passed value is a boolean.\r | |
743 | *\r | |
744 | * @param {Object} value The value to test.\r | |
745 | * @return {Boolean}\r | |
746 | */\r | |
747 | isBoolean: function(value) {\r | |
748 | return typeof value === 'boolean';\r | |
749 | },\r | |
750 | \r | |
751 | /**\r | |
752 | * Returns `true` if the passed value is an HTMLElement\r | |
753 | * @param {Object} value The value to test.\r | |
754 | * @return {Boolean}\r | |
755 | */\r | |
756 | isElement: function(value) {\r | |
757 | return value ? value.nodeType === 1 : false;\r | |
758 | },\r | |
759 | \r | |
760 | /**\r | |
761 | * Returns `true` if the passed value is a TextNode\r | |
762 | * @param {Object} value The value to test.\r | |
763 | * @return {Boolean}\r | |
764 | */\r | |
765 | isTextNode: function(value) {\r | |
766 | return value ? value.nodeName === "#text" : false;\r | |
767 | },\r | |
768 | \r | |
769 | /**\r | |
770 | * Returns `true` if the passed value is defined.\r | |
771 | * @param {Object} value The value to test.\r | |
772 | * @return {Boolean}\r | |
773 | */\r | |
774 | isDefined: function(value) {\r | |
775 | return typeof value !== 'undefined';\r | |
776 | },\r | |
777 | \r | |
778 | /**\r | |
779 | * Returns `true` if the passed value is iterable, that is, if elements of it are addressable using array\r | |
780 | * notation with numeric indices, `false` otherwise.\r | |
781 | *\r | |
782 | * Arrays and function `arguments` objects are iterable. Also HTML collections such as `NodeList` and `HTMLCollection'\r | |
783 | * are iterable.\r | |
784 | *\r | |
785 | * @param {Object} value The value to test\r | |
786 | * @return {Boolean}\r | |
787 | */\r | |
788 | isIterable: function(value) {\r | |
789 | // To be iterable, the object must have a numeric length property and must not be a string or function.\r | |
790 | if (!value || typeof value.length !== 'number' || typeof value === 'string' || Ext.isFunction(value)) {\r | |
791 | return false;\r | |
792 | }\r | |
793 | \r | |
794 | // Certain "standard" collections in IE (such as document.images) do not offer the correct\r | |
795 | // Javascript Object interface; specifically, they lack the propertyIsEnumerable method.\r | |
796 | // And the item property while it does exist is not typeof "function"\r | |
797 | if (!value.propertyIsEnumerable) {\r | |
798 | return !!value.item;\r | |
799 | }\r | |
800 | \r | |
801 | // If it is a regular, interrogatable JS object (not an IE ActiveX object), then...\r | |
802 | // If it has its own property called "length", but not enumerable, it's iterable\r | |
803 | if (value.hasOwnProperty('length') && !value.propertyIsEnumerable('length')) {\r | |
804 | return true;\r | |
805 | }\r | |
806 | \r | |
807 | // Test against whitelist which includes known iterable collection types\r | |
808 | return iterableRe.test(toString.call(value));\r | |
809 | },\r | |
810 | \r | |
811 | /**\r | |
812 | * This method returns `true` if debug is enabled for the specified class. This is\r | |
813 | * done by checking the `Ext.debugConfig.hooks` config for the closest match to the\r | |
814 | * given `className`.\r | |
815 | * @param {String} className The name of the class.\r | |
816 | * @return {Boolean} `true` if debug is enabled for the specified class.\r | |
817 | */\r | |
818 | isDebugEnabled:\r | |
819 | //<debug>\r | |
820 | function (className, defaultEnabled) {\r | |
821 | var debugConfig = Ext.debugConfig.hooks;\r | |
822 | \r | |
823 | if (debugConfig.hasOwnProperty(className)) {\r | |
824 | return debugConfig[className];\r | |
825 | }\r | |
826 | \r | |
827 | var enabled = debugConfig['*'],\r | |
828 | prefixLength = 0;\r | |
829 | \r | |
830 | if (defaultEnabled !== undefined) {\r | |
831 | enabled = defaultEnabled;\r | |
832 | }\r | |
833 | if (!className) {\r | |
834 | return enabled;\r | |
835 | }\r | |
836 | \r | |
837 | for (var prefix in debugConfig) {\r | |
838 | var value = debugConfig[prefix];\r | |
839 | \r | |
840 | // if prefix=='Ext' match 'Ext.foo.Bar' but not 'Ext4.foo.Bar'\r | |
841 | if (className.charAt(prefix.length) === '.') {\r | |
842 | if (className.substring(0, prefix.length) === prefix) {\r | |
843 | if (prefixLength < prefix.length) {\r | |
844 | prefixLength = prefix.length;\r | |
845 | enabled = value;\r | |
846 | }\r | |
847 | }\r | |
848 | }\r | |
849 | }\r | |
850 | \r | |
851 | return enabled;\r | |
852 | } ||\r | |
853 | //</debug>\r | |
854 | emptyFn,\r | |
855 | \r | |
856 | /**\r | |
857 | * Clone simple variables including array, {}-like objects, DOM nodes and Date without keeping the old reference.\r | |
858 | * A reference for the object itself is returned if it's not a direct descendant of Object. For model cloning,\r | |
859 | * see {@link Ext.data.Model#copy Model.copy}.\r | |
860 | *\r | |
861 | * @param {Object} item The variable to clone\r | |
862 | * @return {Object} clone\r | |
863 | */\r | |
864 | clone: function(item) {\r | |
865 | if (item === null || item === undefined) {\r | |
866 | return item;\r | |
867 | }\r | |
868 | \r | |
869 | // DOM nodes\r | |
870 | // TODO proxy this to Ext.Element.clone to handle automatic id attribute changing\r | |
871 | // recursively\r | |
872 | if (item.nodeType && item.cloneNode) {\r | |
873 | return item.cloneNode(true);\r | |
874 | }\r | |
875 | \r | |
876 | var type = toString.call(item),\r | |
877 | i, j, k, clone, key;\r | |
878 | \r | |
879 | // Date\r | |
880 | if (type === '[object Date]') {\r | |
881 | return new Date(item.getTime());\r | |
882 | }\r | |
883 | \r | |
884 | // Array\r | |
885 | if (type === '[object Array]') {\r | |
886 | i = item.length;\r | |
887 | \r | |
888 | clone = [];\r | |
889 | \r | |
890 | while (i--) {\r | |
891 | clone[i] = Ext.clone(item[i]);\r | |
892 | }\r | |
893 | }\r | |
894 | // Object\r | |
895 | else if (type === '[object Object]' && item.constructor === Object) {\r | |
896 | clone = {};\r | |
897 | \r | |
898 | for (key in item) {\r | |
899 | clone[key] = Ext.clone(item[key]);\r | |
900 | }\r | |
901 | \r | |
902 | if (enumerables) {\r | |
903 | for (j = enumerables.length; j--;) {\r | |
904 | k = enumerables[j];\r | |
905 | if (item.hasOwnProperty(k)) {\r | |
906 | clone[k] = item[k];\r | |
907 | }\r | |
908 | }\r | |
909 | }\r | |
910 | }\r | |
911 | \r | |
912 | return clone || item;\r | |
913 | },\r | |
914 | \r | |
915 | /**\r | |
916 | * @private\r | |
917 | * Generate a unique reference of Ext in the global scope, useful for sandboxing\r | |
918 | */\r | |
919 | getUniqueGlobalNamespace: function() {\r | |
920 | var uniqueGlobalNamespace = this.uniqueGlobalNamespace,\r | |
921 | i;\r | |
922 | \r | |
923 | if (uniqueGlobalNamespace === undefined) {\r | |
924 | i = 0;\r | |
925 | \r | |
926 | do {\r | |
927 | uniqueGlobalNamespace = 'ExtBox' + (++i);\r | |
928 | } while (global[uniqueGlobalNamespace] !== undefined);\r | |
929 | \r | |
930 | global[uniqueGlobalNamespace] = Ext;\r | |
931 | this.uniqueGlobalNamespace = uniqueGlobalNamespace;\r | |
932 | }\r | |
933 | \r | |
934 | return uniqueGlobalNamespace;\r | |
935 | },\r | |
936 | \r | |
937 | /**\r | |
938 | * @private\r | |
939 | */\r | |
940 | functionFactoryCache: {},\r | |
941 | \r | |
942 | cacheableFunctionFactory: function() {\r | |
943 | var me = this,\r | |
944 | args = Array.prototype.slice.call(arguments),\r | |
945 | cache = me.functionFactoryCache,\r | |
946 | idx, fn, ln;\r | |
947 | \r | |
948 | if (Ext.isSandboxed) {\r | |
949 | ln = args.length;\r | |
950 | if (ln > 0) {\r | |
951 | ln--;\r | |
952 | args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];\r | |
953 | }\r | |
954 | }\r | |
955 | idx = args.join('');\r | |
956 | fn = cache[idx];\r | |
957 | if (!fn) {\r | |
958 | fn = Function.prototype.constructor.apply(Function.prototype, args);\r | |
959 | \r | |
960 | cache[idx] = fn;\r | |
961 | }\r | |
962 | return fn;\r | |
963 | },\r | |
964 | \r | |
965 | functionFactory: function() {\r | |
966 | var args = Array.prototype.slice.call(arguments),\r | |
967 | ln;\r | |
968 | \r | |
969 | if (Ext.isSandboxed) {\r | |
970 | ln = args.length;\r | |
971 | if (ln > 0) {\r | |
972 | ln--;\r | |
973 | args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];\r | |
974 | }\r | |
975 | }\r | |
976 | \r | |
977 | return Function.prototype.constructor.apply(Function.prototype, args);\r | |
978 | },\r | |
979 | \r | |
980 | /**\r | |
981 | * @private\r | |
982 | */\r | |
983 | Logger: {\r | |
984 | //<feature logger>\r | |
985 | log: function(message, priority) {\r | |
986 | if (message && global.console) {\r | |
987 | if (!priority || !(priority in global.console)) {\r | |
988 | priority = 'log';\r | |
989 | }\r | |
990 | message = '[' + priority.toUpperCase() + '] ' + message;\r | |
991 | global.console[priority](message);\r | |
992 | }\r | |
993 | },\r | |
994 | verbose: function(message) {\r | |
995 | this.log(message, 'verbose');\r | |
996 | },\r | |
997 | info: function(message) {\r | |
998 | this.log(message, 'info');\r | |
999 | },\r | |
1000 | warn: function(message) {\r | |
1001 | this.log(message, 'warn');\r | |
1002 | },\r | |
1003 | error: function(message) {\r | |
1004 | throw new Error(message);\r | |
1005 | },\r | |
1006 | deprecate: function(message) {\r | |
1007 | this.log(message, 'warn');\r | |
1008 | }\r | |
1009 | } || {\r | |
1010 | //</feature>\r | |
1011 | verbose: emptyFn,\r | |
1012 | log: emptyFn,\r | |
1013 | info: emptyFn,\r | |
1014 | warn: emptyFn,\r | |
1015 | error: function(message) {\r | |
1016 | throw new Error(message);\r | |
1017 | },\r | |
1018 | deprecate: emptyFn\r | |
1019 | },\r | |
1020 | \r | |
1021 | /**\r | |
1022 | * @private\r | |
1023 | */\r | |
1024 | getElementById: function(id) {\r | |
1025 | return document.getElementById(id);\r | |
1026 | },\r | |
1027 | \r | |
1028 | /**\r | |
1029 | * @member Ext\r | |
1030 | * @private\r | |
1031 | */\r | |
1032 | splitAndUnescape: (function() {\r | |
1033 | var cache = {};\r | |
1034 | \r | |
1035 | return function(origin, delimiter) {\r | |
1036 | if (!origin) {\r | |
1037 | return [];\r | |
1038 | }\r | |
1039 | else if (!delimiter) {\r | |
1040 | return [origin];\r | |
1041 | }\r | |
1042 | \r | |
1043 | var replaceRe = cache[delimiter] || (cache[delimiter] = new RegExp('\\\\' + delimiter, 'g')),\r | |
1044 | result = [],\r | |
1045 | parts, part;\r | |
1046 | \r | |
1047 | parts = origin.split(delimiter);\r | |
1048 | \r | |
1049 | while ((part = parts.shift()) !== undefined) {\r | |
1050 | // If any of the parts ends with the delimiter that means\r | |
1051 | // the delimiter was escaped and the split was invalid. Roll back.\r | |
1052 | while (part.charAt(part.length - 1) === '\\' && parts.length > 0) {\r | |
1053 | part = part + delimiter + parts.shift();\r | |
1054 | }\r | |
1055 | \r | |
1056 | // Now that we have split the parts, unescape the delimiter char\r | |
1057 | part = part.replace(replaceRe, delimiter);\r | |
1058 | \r | |
1059 | result.push(part);\r | |
1060 | }\r | |
1061 | \r | |
1062 | return result;\r | |
1063 | };\r | |
1064 | })()\r | |
1065 | }); // Ext.apply(Ext\r | |
1066 | \r | |
1067 | Ext.returnTrue.$nullFn = Ext.returnId.$nullFn = true;\r | |
1068 | }());\r |