1 | /* |
---|
2 | * Ext JS Library 2.2.1 |
---|
3 | * Copyright(c) 2006-2009, Ext JS, LLC. |
---|
4 | * licensing@extjs.com |
---|
5 | * |
---|
6 | * http://extjs.com/license |
---|
7 | */ |
---|
8 | |
---|
9 | |
---|
10 | Ext = {version: '2.2.1'}; |
---|
11 | |
---|
12 | // for old browsers |
---|
13 | window["undefined"] = window["undefined"]; |
---|
14 | |
---|
15 | /** |
---|
16 | * @class Ext |
---|
17 | * Ext core utilities and functions. |
---|
18 | * @singleton |
---|
19 | */ |
---|
20 | |
---|
21 | /** |
---|
22 | * Copies all the properties of config to obj. |
---|
23 | * @param {Object} obj The receiver of the properties |
---|
24 | * @param {Object} config The source of the properties |
---|
25 | * @param {Object} defaults A different object that will also be applied for default values |
---|
26 | * @return {Object} returns obj |
---|
27 | * @member Ext apply |
---|
28 | */ |
---|
29 | Ext.apply = function(o, c, defaults){ |
---|
30 | if(defaults){ |
---|
31 | // no "this" reference for friendly out of scope calls |
---|
32 | Ext.apply(o, defaults); |
---|
33 | } |
---|
34 | if(o && c && typeof c == 'object'){ |
---|
35 | for(var p in c){ |
---|
36 | o[p] = c[p]; |
---|
37 | } |
---|
38 | } |
---|
39 | return o; |
---|
40 | }; |
---|
41 | |
---|
42 | (function(){ |
---|
43 | var idSeed = 0; |
---|
44 | var ua = navigator.userAgent.toLowerCase(); |
---|
45 | |
---|
46 | var isStrict = document.compatMode == "CSS1Compat", |
---|
47 | isOpera = ua.indexOf("opera") > -1, |
---|
48 | isChrome = ua.indexOf("chrome") > -1, |
---|
49 | isSafari = !isChrome && (/webkit|khtml/).test(ua), |
---|
50 | isSafari3 = isSafari && ua.indexOf('webkit/5') != -1, |
---|
51 | isIE = !isOpera && ua.indexOf("msie") > -1, |
---|
52 | isIE7 = !isOpera && ua.indexOf("msie 7") > -1, |
---|
53 | isIE8 = !isOpera && ua.indexOf("msie 8") > -1, |
---|
54 | isGecko = !isSafari && !isChrome && ua.indexOf("gecko") > -1, |
---|
55 | isGecko3 = isGecko && ua.indexOf("rv:1.9") > -1, |
---|
56 | isBorderBox = isIE && !isStrict, |
---|
57 | isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1), |
---|
58 | isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1), |
---|
59 | isAir = (ua.indexOf("adobeair") != -1), |
---|
60 | isLinux = (ua.indexOf("linux") != -1), |
---|
61 | isSecure = window.location.href.toLowerCase().indexOf("https") === 0; |
---|
62 | |
---|
63 | // remove css image flicker |
---|
64 | if(isIE && !isIE7){ |
---|
65 | try{ |
---|
66 | document.execCommand("BackgroundImageCache", false, true); |
---|
67 | }catch(e){} |
---|
68 | } |
---|
69 | |
---|
70 | Ext.apply(Ext, { |
---|
71 | /** |
---|
72 | * True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode |
---|
73 | * @type Boolean |
---|
74 | */ |
---|
75 | isStrict : isStrict, |
---|
76 | /** |
---|
77 | * True if the page is running over SSL |
---|
78 | * @type Boolean |
---|
79 | */ |
---|
80 | isSecure : isSecure, |
---|
81 | /** |
---|
82 | * True when the document is fully initialized and ready for action |
---|
83 | * @type Boolean |
---|
84 | */ |
---|
85 | isReady : false, |
---|
86 | |
---|
87 | /** |
---|
88 | * True to automatically uncache orphaned Ext.Elements periodically (defaults to true) |
---|
89 | * @type Boolean |
---|
90 | */ |
---|
91 | enableGarbageCollector : true, |
---|
92 | |
---|
93 | /** |
---|
94 | * True to automatically purge event listeners after uncaching an element (defaults to false). |
---|
95 | * Note: this only happens if enableGarbageCollector is true. |
---|
96 | * @type Boolean |
---|
97 | */ |
---|
98 | enableListenerCollection:false, |
---|
99 | |
---|
100 | |
---|
101 | /** |
---|
102 | * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent |
---|
103 | * the IE insecure content warning (defaults to javascript:false). |
---|
104 | * @type String |
---|
105 | */ |
---|
106 | SSL_SECURE_URL : "javascript:false", |
---|
107 | |
---|
108 | /** |
---|
109 | * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images. (Defaults to |
---|
110 | * "http://extjs.com/s.gif" and you should change this to a URL on your server). |
---|
111 | * @type String |
---|
112 | */ |
---|
113 | BLANK_IMAGE_URL : "http:/"+"/extjs.com/s.gif", |
---|
114 | |
---|
115 | /** |
---|
116 | * A reusable empty function |
---|
117 | * @property |
---|
118 | * @type Function |
---|
119 | */ |
---|
120 | emptyFn : function(){}, |
---|
121 | |
---|
122 | /** |
---|
123 | * Copies all the properties of config to obj if they don't already exist. |
---|
124 | * @param {Object} obj The receiver of the properties |
---|
125 | * @param {Object} config The source of the properties |
---|
126 | * @return {Object} returns obj |
---|
127 | */ |
---|
128 | applyIf : function(o, c){ |
---|
129 | if(o && c){ |
---|
130 | for(var p in c){ |
---|
131 | if(typeof o[p] == "undefined"){ o[p] = c[p]; } |
---|
132 | } |
---|
133 | } |
---|
134 | return o; |
---|
135 | }, |
---|
136 | |
---|
137 | /** |
---|
138 | * Applies event listeners to elements by selectors when the document is ready. |
---|
139 | * The event name is specified with an @ suffix. |
---|
140 | <pre><code> |
---|
141 | Ext.addBehaviors({ |
---|
142 | // add a listener for click on all anchors in element with id foo |
---|
143 | '#foo a@click' : function(e, t){ |
---|
144 | // do something |
---|
145 | }, |
---|
146 | |
---|
147 | // add the same listener to multiple selectors (separated by comma BEFORE the @) |
---|
148 | '#foo a, #bar span.some-class@mouseover' : function(){ |
---|
149 | // do something |
---|
150 | } |
---|
151 | }); |
---|
152 | </code></pre> |
---|
153 | * @param {Object} obj The list of behaviors to apply |
---|
154 | */ |
---|
155 | addBehaviors : function(o){ |
---|
156 | if(!Ext.isReady){ |
---|
157 | Ext.onReady(function(){ |
---|
158 | Ext.addBehaviors(o); |
---|
159 | }); |
---|
160 | return; |
---|
161 | } |
---|
162 | var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times |
---|
163 | for(var b in o){ |
---|
164 | var parts = b.split('@'); |
---|
165 | if(parts[1]){ // for Object prototype breakers |
---|
166 | var s = parts[0]; |
---|
167 | if(!cache[s]){ |
---|
168 | cache[s] = Ext.select(s); |
---|
169 | } |
---|
170 | cache[s].on(parts[1], o[b]); |
---|
171 | } |
---|
172 | } |
---|
173 | cache = null; |
---|
174 | }, |
---|
175 | |
---|
176 | /** |
---|
177 | * Generates unique ids. If the element already has an id, it is unchanged |
---|
178 | * @param {Mixed} el (optional) The element to generate an id for |
---|
179 | * @param {String} prefix (optional) Id prefix (defaults "ext-gen") |
---|
180 | * @return {String} The generated Id. |
---|
181 | */ |
---|
182 | id : function(el, prefix){ |
---|
183 | prefix = prefix || "ext-gen"; |
---|
184 | el = Ext.getDom(el); |
---|
185 | var id = prefix + (++idSeed); |
---|
186 | return el ? (el.id ? el.id : (el.id = id)) : id; |
---|
187 | }, |
---|
188 | |
---|
189 | /** |
---|
190 | * Extends one class with another class and optionally overrides members with the passed literal. This class |
---|
191 | * also adds the function "override()" to the class that can be used to override |
---|
192 | * members on an instance. |
---|
193 | * * <p> |
---|
194 | * This function also supports a 2-argument call in which the subclass's constructor is |
---|
195 | * not passed as an argument. In this form, the parameters are as follows:</p><p> |
---|
196 | * <div class="mdetail-params"><ul> |
---|
197 | * <li><code>superclass</code> |
---|
198 | * <div class="sub-desc">The class being extended</div></li> |
---|
199 | * <li><code>overrides</code> |
---|
200 | * <div class="sub-desc">A literal with members which are copied into the subclass's |
---|
201 | * prototype, and are therefore shared among all instances of the new class.<p> |
---|
202 | * This may contain a special member named <tt><b>constructor</b></tt>. This is used |
---|
203 | * to define the constructor of the new class, and is returned. If this property is |
---|
204 | * <i>not</i> specified, a constructor is generated and returned which just calls the |
---|
205 | * superclass's constructor passing on its parameters.</p></div></li> |
---|
206 | * </ul></div></p><p> |
---|
207 | * For example, to create a subclass of the Ext GridPanel: |
---|
208 | * <pre><code> |
---|
209 | MyGridPanel = Ext.extend(Ext.grid.GridPanel, { |
---|
210 | constructor: function(config) { |
---|
211 | // Your preprocessing here |
---|
212 | MyGridPanel.superclass.constructor.apply(this, arguments); |
---|
213 | // Your postprocessing here |
---|
214 | }, |
---|
215 | |
---|
216 | yourMethod: function() { |
---|
217 | // etc. |
---|
218 | } |
---|
219 | }); |
---|
220 | </code></pre> |
---|
221 | * </p> |
---|
222 | * @param {Function} subclass The class inheriting the functionality |
---|
223 | * @param {Function} superclass The class being extended |
---|
224 | * @param {Object} overrides (optional) A literal with members which are copied into the subclass's |
---|
225 | * prototype, and are therefore shared between all instances of the new class. |
---|
226 | * @return {Function} The subclass constructor. |
---|
227 | * @method extend |
---|
228 | */ |
---|
229 | extend : function(){ |
---|
230 | // inline overrides |
---|
231 | var io = function(o){ |
---|
232 | for(var m in o){ |
---|
233 | this[m] = o[m]; |
---|
234 | } |
---|
235 | }; |
---|
236 | var oc = Object.prototype.constructor; |
---|
237 | |
---|
238 | return function(sb, sp, overrides){ |
---|
239 | if(typeof sp == 'object'){ |
---|
240 | overrides = sp; |
---|
241 | sp = sb; |
---|
242 | sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; |
---|
243 | } |
---|
244 | var F = function(){}, sbp, spp = sp.prototype; |
---|
245 | F.prototype = spp; |
---|
246 | sbp = sb.prototype = new F(); |
---|
247 | sbp.constructor=sb; |
---|
248 | sb.superclass=spp; |
---|
249 | if(spp.constructor == oc){ |
---|
250 | spp.constructor=sp; |
---|
251 | } |
---|
252 | sb.override = function(o){ |
---|
253 | Ext.override(sb, o); |
---|
254 | }; |
---|
255 | sbp.override = io; |
---|
256 | Ext.override(sb, overrides); |
---|
257 | sb.extend = function(o){Ext.extend(sb, o);}; |
---|
258 | return sb; |
---|
259 | }; |
---|
260 | }(), |
---|
261 | |
---|
262 | /** |
---|
263 | * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name. |
---|
264 | * Usage:<pre><code> |
---|
265 | Ext.override(MyClass, { |
---|
266 | newMethod1: function(){ |
---|
267 | // etc. |
---|
268 | }, |
---|
269 | newMethod2: function(foo){ |
---|
270 | // etc. |
---|
271 | } |
---|
272 | }); |
---|
273 | </code></pre> |
---|
274 | * @param {Object} origclass The class to override |
---|
275 | * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal |
---|
276 | * containing one or more methods. |
---|
277 | * @method override |
---|
278 | */ |
---|
279 | override : function(origclass, overrides){ |
---|
280 | if(overrides){ |
---|
281 | var p = origclass.prototype; |
---|
282 | for(var method in overrides){ |
---|
283 | p[method] = overrides[method]; |
---|
284 | } |
---|
285 | if(Ext.isIE && overrides.toString != origclass.toString){ |
---|
286 | p.toString = overrides.toString; |
---|
287 | } |
---|
288 | } |
---|
289 | }, |
---|
290 | |
---|
291 | /** |
---|
292 | * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage: |
---|
293 | * <pre><code> |
---|
294 | Ext.namespace('Company', 'Company.data'); |
---|
295 | Company.Widget = function() { ... } |
---|
296 | Company.data.CustomStore = function(config) { ... } |
---|
297 | </code></pre> |
---|
298 | * @param {String} namespace1 |
---|
299 | * @param {String} namespace2 |
---|
300 | * @param {String} etc |
---|
301 | * @method namespace |
---|
302 | */ |
---|
303 | namespace : function(){ |
---|
304 | var a=arguments, o=null, i, j, d, rt; |
---|
305 | for (i=0; i<a.length; ++i) { |
---|
306 | d=a[i].split("."); |
---|
307 | rt = d[0]; |
---|
308 | eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';'); |
---|
309 | for (j=1; j<d.length; ++j) { |
---|
310 | o[d[j]]=o[d[j]] || {}; |
---|
311 | o=o[d[j]]; |
---|
312 | } |
---|
313 | } |
---|
314 | }, |
---|
315 | |
---|
316 | /** |
---|
317 | * Takes an object and converts it to an encoded URL. e.g. Ext.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value. |
---|
318 | * @param {Object} o |
---|
319 | * @return {String} |
---|
320 | */ |
---|
321 | urlEncode : function(o){ |
---|
322 | if(!o){ |
---|
323 | return ""; |
---|
324 | } |
---|
325 | var buf = []; |
---|
326 | for(var key in o){ |
---|
327 | var ov = o[key], k = encodeURIComponent(key); |
---|
328 | var type = typeof ov; |
---|
329 | if(type == 'undefined'){ |
---|
330 | buf.push(k, "=&"); |
---|
331 | }else if(type != "function" && type != "object"){ |
---|
332 | buf.push(k, "=", encodeURIComponent(ov), "&"); |
---|
333 | }else if(Ext.isDate(ov)){ |
---|
334 | var s = Ext.encode(ov).replace(/"/g, ''); |
---|
335 | buf.push(k, "=", s, "&"); |
---|
336 | }else if(Ext.isArray(ov)){ |
---|
337 | if (ov.length) { |
---|
338 | for(var i = 0, len = ov.length; i < len; i++) { |
---|
339 | buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&"); |
---|
340 | } |
---|
341 | } else { |
---|
342 | buf.push(k, "=&"); |
---|
343 | } |
---|
344 | } |
---|
345 | } |
---|
346 | buf.pop(); |
---|
347 | return buf.join(""); |
---|
348 | }, |
---|
349 | |
---|
350 | /** |
---|
351 | * Takes an encoded URL and and converts it to an object. e.g. Ext.urlDecode("foo=1&bar=2"); would return {foo: "1", bar: "2"} |
---|
352 | * or Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); would return {foo: "1", bar: ["2", "3", "4"]}. |
---|
353 | * @param {String} string |
---|
354 | * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false). |
---|
355 | * @return {Object} A literal with members |
---|
356 | */ |
---|
357 | urlDecode : function(string, overwrite){ |
---|
358 | if(!string || !string.length){ |
---|
359 | return {}; |
---|
360 | } |
---|
361 | var obj = {}; |
---|
362 | var pairs = string.split('&'); |
---|
363 | var pair, name, value; |
---|
364 | for(var i = 0, len = pairs.length; i < len; i++){ |
---|
365 | pair = pairs[i].split('='); |
---|
366 | name = decodeURIComponent(pair[0]); |
---|
367 | value = decodeURIComponent(pair[1]); |
---|
368 | if(overwrite !== true){ |
---|
369 | if(typeof obj[name] == "undefined"){ |
---|
370 | obj[name] = value; |
---|
371 | }else if(typeof obj[name] == "string"){ |
---|
372 | obj[name] = [obj[name]]; |
---|
373 | obj[name].push(value); |
---|
374 | }else{ |
---|
375 | obj[name].push(value); |
---|
376 | } |
---|
377 | }else{ |
---|
378 | obj[name] = value; |
---|
379 | } |
---|
380 | } |
---|
381 | return obj; |
---|
382 | }, |
---|
383 | |
---|
384 | /** |
---|
385 | * Iterates an array calling the passed function with each item, stopping if your function returns false. If the |
---|
386 | * passed array is not really an array, your function is called once with it. |
---|
387 | * The supplied function is called with (Object item, Number index, Array allItems). |
---|
388 | * @param {Array/NodeList/Mixed} array |
---|
389 | * @param {Function} fn |
---|
390 | * @param {Object} scope |
---|
391 | */ |
---|
392 | each : function(array, fn, scope){ |
---|
393 | if(typeof array.length == "undefined" || typeof array == "string"){ |
---|
394 | array = [array]; |
---|
395 | } |
---|
396 | for(var i = 0, len = array.length; i < len; i++){ |
---|
397 | if(fn.call(scope || array[i], array[i], i, array) === false){ return i; }; |
---|
398 | } |
---|
399 | }, |
---|
400 | |
---|
401 | // deprecated |
---|
402 | combine : function(){ |
---|
403 | var as = arguments, l = as.length, r = []; |
---|
404 | for(var i = 0; i < l; i++){ |
---|
405 | var a = as[i]; |
---|
406 | if(Ext.isArray(a)){ |
---|
407 | r = r.concat(a); |
---|
408 | }else if(a.length !== undefined && !a.substr){ |
---|
409 | r = r.concat(Array.prototype.slice.call(a, 0)); |
---|
410 | }else{ |
---|
411 | r.push(a); |
---|
412 | } |
---|
413 | } |
---|
414 | return r; |
---|
415 | }, |
---|
416 | |
---|
417 | /** |
---|
418 | * Escapes the passed string for use in a regular expression |
---|
419 | * @param {String} str |
---|
420 | * @return {String} |
---|
421 | */ |
---|
422 | escapeRe : function(s) { |
---|
423 | return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1"); |
---|
424 | }, |
---|
425 | |
---|
426 | // internal |
---|
427 | callback : function(cb, scope, args, delay){ |
---|
428 | if(typeof cb == "function"){ |
---|
429 | if(delay){ |
---|
430 | cb.defer(delay, scope, args || []); |
---|
431 | }else{ |
---|
432 | cb.apply(scope, args || []); |
---|
433 | } |
---|
434 | } |
---|
435 | }, |
---|
436 | |
---|
437 | /** |
---|
438 | * Return the dom node for the passed string (id), dom node, or Ext.Element |
---|
439 | * @param {Mixed} el |
---|
440 | * @return HTMLElement |
---|
441 | */ |
---|
442 | getDom : function(el){ |
---|
443 | if(!el || !document){ |
---|
444 | return null; |
---|
445 | } |
---|
446 | return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el); |
---|
447 | }, |
---|
448 | |
---|
449 | /** |
---|
450 | * Returns the current HTML document object as an {@link Ext.Element}. |
---|
451 | * @return Ext.Element The document |
---|
452 | */ |
---|
453 | getDoc : function(){ |
---|
454 | return Ext.get(document); |
---|
455 | }, |
---|
456 | |
---|
457 | /** |
---|
458 | * Returns the current document body as an {@link Ext.Element}. |
---|
459 | * @return Ext.Element The document body |
---|
460 | */ |
---|
461 | getBody : function(){ |
---|
462 | return Ext.get(document.body || document.documentElement); |
---|
463 | }, |
---|
464 | |
---|
465 | /** |
---|
466 | * Shorthand for {@link Ext.ComponentMgr#get} |
---|
467 | * @param {String} id |
---|
468 | * @return Ext.Component |
---|
469 | */ |
---|
470 | getCmp : function(id){ |
---|
471 | return Ext.ComponentMgr.get(id); |
---|
472 | }, |
---|
473 | |
---|
474 | /** |
---|
475 | * Utility method for validating that a value is numeric, returning the specified default value if it is not. |
---|
476 | * @param {Mixed} value Should be a number, but any type will be handled appropriately |
---|
477 | * @param {Number} defaultValue The value to return if the original value is non-numeric |
---|
478 | * @return {Number} Value, if numeric, else defaultValue |
---|
479 | */ |
---|
480 | num : function(v, defaultValue){ |
---|
481 | if(typeof v != 'number' || isNaN(v)){ |
---|
482 | return defaultValue; |
---|
483 | } |
---|
484 | return v; |
---|
485 | }, |
---|
486 | |
---|
487 | /** |
---|
488 | * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the |
---|
489 | * DOM (if applicable) and calling their destroy functions (if available). This method is primarily |
---|
490 | * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of |
---|
491 | * {@link Ext.util.Observable} can be passed in. Any number of elements and/or components can be |
---|
492 | * passed into this function in a single call as separate arguments. |
---|
493 | * @param {Mixed} arg1 An {@link Ext.Element} or {@link Ext.Component} to destroy |
---|
494 | * @param {Mixed} arg2 (optional) |
---|
495 | * @param {Mixed} etc... (optional) |
---|
496 | */ |
---|
497 | destroy : function(){ |
---|
498 | for(var i = 0, a = arguments, len = a.length; i < len; i++) { |
---|
499 | var as = a[i]; |
---|
500 | if(as){ |
---|
501 | if(typeof as.destroy == 'function'){ |
---|
502 | as.destroy(); |
---|
503 | } |
---|
504 | else if(as.dom){ |
---|
505 | as.removeAllListeners(); |
---|
506 | as.remove(); |
---|
507 | } |
---|
508 | } |
---|
509 | } |
---|
510 | }, |
---|
511 | |
---|
512 | /** |
---|
513 | * Removes a DOM node from the document. The body node will be ignored if passed in. |
---|
514 | * @param {HTMLElement} node The node to remove |
---|
515 | */ |
---|
516 | removeNode : isIE ? function(){ |
---|
517 | var d; |
---|
518 | return function(n){ |
---|
519 | if(n && n.tagName != 'BODY'){ |
---|
520 | d = d || document.createElement('div'); |
---|
521 | d.appendChild(n); |
---|
522 | d.innerHTML = ''; |
---|
523 | } |
---|
524 | } |
---|
525 | }() : function(n){ |
---|
526 | if(n && n.parentNode && n.tagName != 'BODY'){ |
---|
527 | n.parentNode.removeChild(n); |
---|
528 | } |
---|
529 | }, |
---|
530 | |
---|
531 | // inpired by a similar function in mootools library |
---|
532 | /** |
---|
533 | * Returns the type of object that is passed in. If the object passed in is null or undefined it |
---|
534 | * return false otherwise it returns one of the following values:<ul> |
---|
535 | * <li><b>string</b>: If the object passed is a string</li> |
---|
536 | * <li><b>number</b>: If the object passed is a number</li> |
---|
537 | * <li><b>boolean</b>: If the object passed is a boolean value</li> |
---|
538 | * <li><b>date</b>: If the object passed is a Date object</li> |
---|
539 | * <li><b>function</b>: If the object passed is a function reference</li> |
---|
540 | * <li><b>object</b>: If the object passed is an object</li> |
---|
541 | * <li><b>array</b>: If the object passed is an array</li> |
---|
542 | * <li><b>regexp</b>: If the object passed is a regular expression</li> |
---|
543 | * <li><b>element</b>: If the object passed is a DOM Element</li> |
---|
544 | * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li> |
---|
545 | * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li> |
---|
546 | * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li> |
---|
547 | * @param {Mixed} object |
---|
548 | * @return {String} |
---|
549 | */ |
---|
550 | type : function(o){ |
---|
551 | if(o === undefined || o === null){ |
---|
552 | return false; |
---|
553 | } |
---|
554 | if(o.htmlElement){ |
---|
555 | return 'element'; |
---|
556 | } |
---|
557 | var t = typeof o; |
---|
558 | if(t == 'object' && o.nodeName) { |
---|
559 | switch(o.nodeType) { |
---|
560 | case 1: return 'element'; |
---|
561 | case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace'; |
---|
562 | } |
---|
563 | } |
---|
564 | if(t == 'object' || t == 'function') { |
---|
565 | switch(o.constructor) { |
---|
566 | case Array: return 'array'; |
---|
567 | case RegExp: return 'regexp'; |
---|
568 | case Date: return 'date'; |
---|
569 | } |
---|
570 | if(typeof o.length == 'number' && typeof o.item == 'function') { |
---|
571 | return 'nodelist'; |
---|
572 | } |
---|
573 | } |
---|
574 | return t; |
---|
575 | }, |
---|
576 | |
---|
577 | /** |
---|
578 | * Returns true if the passed value is null, undefined or an empty string. |
---|
579 | * @param {Mixed} value The value to test |
---|
580 | * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false) |
---|
581 | * @return {Boolean} |
---|
582 | */ |
---|
583 | isEmpty : function(v, allowBlank){ |
---|
584 | return v === null || v === undefined || (!allowBlank ? v === '' : false); |
---|
585 | }, |
---|
586 | |
---|
587 | /** |
---|
588 | * Utility method for validating that a value is non-empty (i.e. i) not null, ii) not undefined, and iii) not an empty string), |
---|
589 | * returning the specified default value if it is. |
---|
590 | * @param {Mixed} value The value to test |
---|
591 | * @param {Mixed} defaultValue The value to return if the original value is empty |
---|
592 | * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false) |
---|
593 | * @return {Mixed} value, if non-empty, else defaultValue |
---|
594 | */ |
---|
595 | value : function(v, defaultValue, allowBlank){ |
---|
596 | return Ext.isEmpty(v, allowBlank) ? defaultValue : v; |
---|
597 | }, |
---|
598 | |
---|
599 | /** |
---|
600 | * Returns true if the passed object is a JavaScript array, otherwise false. |
---|
601 | * @param {Object} The object to test |
---|
602 | * @return {Boolean} |
---|
603 | */ |
---|
604 | isArray : function(v){ |
---|
605 | return v && typeof v.length == 'number' && typeof v.splice == 'function'; |
---|
606 | }, |
---|
607 | |
---|
608 | /** |
---|
609 | * Returns true if the passed object is a JavaScript date object, otherwise false. |
---|
610 | * @param {Object} The object to test |
---|
611 | * @return {Boolean} |
---|
612 | */ |
---|
613 | isDate : function(v){ |
---|
614 | return v && typeof v.getFullYear == 'function'; |
---|
615 | }, |
---|
616 | |
---|
617 | /** |
---|
618 | * True if the detected browser is Opera. |
---|
619 | * @type Boolean |
---|
620 | */ |
---|
621 | isOpera : isOpera, |
---|
622 | /** |
---|
623 | * True if the detected browser is Chrome. |
---|
624 | * @type Boolean |
---|
625 | */ |
---|
626 | isChrome : isChrome, |
---|
627 | /** |
---|
628 | * True if the detected browser is Safari. |
---|
629 | * @type Boolean |
---|
630 | */ |
---|
631 | isSafari : isSafari, |
---|
632 | /** |
---|
633 | * True if the detected browser is Safari 3.x. |
---|
634 | * @type Boolean |
---|
635 | */ |
---|
636 | isSafari3 : isSafari3, |
---|
637 | /** |
---|
638 | * True if the detected browser is Safari 2.x. |
---|
639 | * @type Boolean |
---|
640 | */ |
---|
641 | isSafari2 : isSafari && !isSafari3, |
---|
642 | /** |
---|
643 | * True if the detected browser is Internet Explorer. |
---|
644 | * @type Boolean |
---|
645 | */ |
---|
646 | isIE : isIE, |
---|
647 | /** |
---|
648 | * True if the detected browser is Internet Explorer 6.x. |
---|
649 | * @type Boolean |
---|
650 | */ |
---|
651 | isIE6 : isIE && !isIE7 && !isIE8, |
---|
652 | /** |
---|
653 | * True if the detected browser is Internet Explorer 7.x. |
---|
654 | * @type Boolean |
---|
655 | */ |
---|
656 | isIE7 : isIE7, |
---|
657 | /** |
---|
658 | * True if the detected browser is Internet Explorer 8.x. |
---|
659 | * @type Boolean |
---|
660 | */ |
---|
661 | isIE8 : isIE8, |
---|
662 | /** |
---|
663 | * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox). |
---|
664 | * @type Boolean |
---|
665 | */ |
---|
666 | isGecko : isGecko, |
---|
667 | /** |
---|
668 | * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x). |
---|
669 | * @type Boolean |
---|
670 | */ |
---|
671 | isGecko2 : isGecko && !isGecko3, |
---|
672 | /** |
---|
673 | * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x). |
---|
674 | * @type Boolean |
---|
675 | */ |
---|
676 | isGecko3 : isGecko3, |
---|
677 | /** |
---|
678 | * True if the detected browser is Internet Explorer running in non-strict mode. |
---|
679 | * @type Boolean |
---|
680 | */ |
---|
681 | isBorderBox : isBorderBox, |
---|
682 | /** |
---|
683 | * True if the detected platform is Linux. |
---|
684 | * @type Boolean |
---|
685 | */ |
---|
686 | isLinux : isLinux, |
---|
687 | /** |
---|
688 | * True if the detected platform is Windows. |
---|
689 | * @type Boolean |
---|
690 | */ |
---|
691 | isWindows : isWindows, |
---|
692 | /** |
---|
693 | * True if the detected platform is Mac OS. |
---|
694 | * @type Boolean |
---|
695 | */ |
---|
696 | isMac : isMac, |
---|
697 | /** |
---|
698 | * True if the detected platform is Adobe Air. |
---|
699 | * @type Boolean |
---|
700 | */ |
---|
701 | isAir : isAir, |
---|
702 | |
---|
703 | /** |
---|
704 | * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash, |
---|
705 | * you may want to set this to true. |
---|
706 | * @type Boolean |
---|
707 | */ |
---|
708 | useShims : ((isIE && !isIE7) || (isMac && isGecko && !isGecko3)) |
---|
709 | }); |
---|
710 | |
---|
711 | // in intellij using keyword "namespace" causes parsing errors |
---|
712 | Ext.ns = Ext.namespace; |
---|
713 | })(); |
---|
714 | |
---|
715 | Ext.ns("Ext", "Ext.util", "Ext.grid", "Ext.dd", "Ext.tree", "Ext.data", |
---|
716 | "Ext.form", "Ext.menu", "Ext.state", "Ext.lib", "Ext.layout", "Ext.app", "Ext.ux"); |
---|
717 | |
---|
718 | |
---|
719 | /** |
---|
720 | * @class Function |
---|
721 | * These functions are available on every Function object (any JavaScript function). |
---|
722 | */ |
---|
723 | Ext.apply(Function.prototype, { |
---|
724 | /** |
---|
725 | * Creates a callback that passes arguments[0], arguments[1], arguments[2], ... |
---|
726 | * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code> |
---|
727 | * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the |
---|
728 | * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always |
---|
729 | * executes in the window scope. |
---|
730 | * <p>This method is required when you want to pass arguments to a callback function. If no arguments |
---|
731 | * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn). |
---|
732 | * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function |
---|
733 | * would simply execute immediately when the code is parsed. Example usage: |
---|
734 | * <pre><code> |
---|
735 | var sayHi = function(name){ |
---|
736 | alert('Hi, ' + name); |
---|
737 | } |
---|
738 | |
---|
739 | // clicking the button alerts "Hi, Fred" |
---|
740 | new Ext.Button({ |
---|
741 | text: 'Say Hi', |
---|
742 | renderTo: Ext.getBody(), |
---|
743 | handler: sayHi.createCallback('Fred') |
---|
744 | }); |
---|
745 | </code></pre> |
---|
746 | * @return {Function} The new function |
---|
747 | */ |
---|
748 | createCallback : function(/*args...*/){ |
---|
749 | // make args available, in function below |
---|
750 | var args = arguments; |
---|
751 | var method = this; |
---|
752 | return function() { |
---|
753 | return method.apply(window, args); |
---|
754 | }; |
---|
755 | }, |
---|
756 | |
---|
757 | /** |
---|
758 | * Creates a delegate (callback) that sets the scope to obj. |
---|
759 | * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code> |
---|
760 | * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the |
---|
761 | * callback points to obj. Example usage: |
---|
762 | * <pre><code> |
---|
763 | var sayHi = function(name){ |
---|
764 | // Note this use of "this.text" here. This function expects to |
---|
765 | // execute within a scope that contains a text property. In this |
---|
766 | // example, the "this" variable is pointing to the btn object that |
---|
767 | // was passed in createDelegate below. |
---|
768 | alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.'); |
---|
769 | } |
---|
770 | |
---|
771 | var btn = new Ext.Button({ |
---|
772 | text: 'Say Hi', |
---|
773 | renderTo: Ext.getBody() |
---|
774 | }); |
---|
775 | |
---|
776 | // This callback will execute in the scope of the |
---|
777 | // button instance. Clicking the button alerts |
---|
778 | // "Hi, Fred. You clicked the "Say Hi" button." |
---|
779 | btn.on('click', sayHi.createDelegate(btn, ['Fred'])); |
---|
780 | </code></pre> |
---|
781 | * @param {Object} obj (optional) The object for which the scope is set |
---|
782 | * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller) |
---|
783 | * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding, |
---|
784 | * if a number the args are inserted at the specified position |
---|
785 | * @return {Function} The new function |
---|
786 | */ |
---|
787 | createDelegate : function(obj, args, appendArgs){ |
---|
788 | var method = this; |
---|
789 | return function() { |
---|
790 | var callArgs = args || arguments; |
---|
791 | if(appendArgs === true){ |
---|
792 | callArgs = Array.prototype.slice.call(arguments, 0); |
---|
793 | callArgs = callArgs.concat(args); |
---|
794 | }else if(typeof appendArgs == "number"){ |
---|
795 | callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first |
---|
796 | var applyArgs = [appendArgs, 0].concat(args); // create method call params |
---|
797 | Array.prototype.splice.apply(callArgs, applyArgs); // splice them in |
---|
798 | } |
---|
799 | return method.apply(obj || window, callArgs); |
---|
800 | }; |
---|
801 | }, |
---|
802 | |
---|
803 | /** |
---|
804 | * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage: |
---|
805 | * <pre><code> |
---|
806 | var sayHi = function(name){ |
---|
807 | alert('Hi, ' + name); |
---|
808 | } |
---|
809 | |
---|
810 | // executes immediately: |
---|
811 | sayHi('Fred'); |
---|
812 | |
---|
813 | // executes after 2 seconds: |
---|
814 | sayHi.defer(2000, this, ['Fred']); |
---|
815 | |
---|
816 | // this syntax is sometimes useful for deferring |
---|
817 | // execution of an anonymous function: |
---|
818 | (function(){ |
---|
819 | alert('Anonymous'); |
---|
820 | }).defer(100); |
---|
821 | </code></pre> |
---|
822 | * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately) |
---|
823 | * @param {Object} obj (optional) The object for which the scope is set |
---|
824 | * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller) |
---|
825 | * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding, |
---|
826 | * if a number the args are inserted at the specified position |
---|
827 | * @return {Number} The timeout id that can be used with clearTimeout |
---|
828 | */ |
---|
829 | defer : function(millis, obj, args, appendArgs){ |
---|
830 | var fn = this.createDelegate(obj, args, appendArgs); |
---|
831 | if(millis){ |
---|
832 | return setTimeout(fn, millis); |
---|
833 | } |
---|
834 | fn(); |
---|
835 | return 0; |
---|
836 | }, |
---|
837 | |
---|
838 | /** |
---|
839 | * Create a combined function call sequence of the original function + the passed function. |
---|
840 | * The resulting function returns the results of the original function. |
---|
841 | * The passed fcn is called with the parameters of the original function. Example usage: |
---|
842 | * <pre><code> |
---|
843 | var sayHi = function(name){ |
---|
844 | alert('Hi, ' + name); |
---|
845 | } |
---|
846 | |
---|
847 | sayHi('Fred'); // alerts "Hi, Fred" |
---|
848 | |
---|
849 | var sayGoodbye = sayHi.createSequence(function(name){ |
---|
850 | alert('Bye, ' + name); |
---|
851 | }); |
---|
852 | |
---|
853 | sayGoodbye('Fred'); // both alerts show |
---|
854 | </code></pre> |
---|
855 | * @param {Function} fcn The function to sequence |
---|
856 | * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window) |
---|
857 | * @return {Function} The new function |
---|
858 | */ |
---|
859 | createSequence : function(fcn, scope){ |
---|
860 | if(typeof fcn != "function"){ |
---|
861 | return this; |
---|
862 | } |
---|
863 | var method = this; |
---|
864 | return function() { |
---|
865 | var retval = method.apply(this || window, arguments); |
---|
866 | fcn.apply(scope || this || window, arguments); |
---|
867 | return retval; |
---|
868 | }; |
---|
869 | }, |
---|
870 | |
---|
871 | /** |
---|
872 | * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, |
---|
873 | * the original one is not called. The resulting function returns the results of the original function. |
---|
874 | * The passed fcn is called with the parameters of the original function. Example usage: |
---|
875 | * <pre><code> |
---|
876 | var sayHi = function(name){ |
---|
877 | alert('Hi, ' + name); |
---|
878 | } |
---|
879 | |
---|
880 | sayHi('Fred'); // alerts "Hi, Fred" |
---|
881 | |
---|
882 | // create a new function that validates input without |
---|
883 | // directly modifying the original function: |
---|
884 | var sayHiToFriend = sayHi.createInterceptor(function(name){ |
---|
885 | return name == 'Brian'; |
---|
886 | }); |
---|
887 | |
---|
888 | sayHiToFriend('Fred'); // no alert |
---|
889 | sayHiToFriend('Brian'); // alerts "Hi, Brian" |
---|
890 | </code></pre> |
---|
891 | * @param {Function} fcn The function to call before the original |
---|
892 | * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window) |
---|
893 | * @return {Function} The new function |
---|
894 | */ |
---|
895 | createInterceptor : function(fcn, scope){ |
---|
896 | if(typeof fcn != "function"){ |
---|
897 | return this; |
---|
898 | } |
---|
899 | var method = this; |
---|
900 | return function() { |
---|
901 | fcn.target = this; |
---|
902 | fcn.method = method; |
---|
903 | if(fcn.apply(scope || this || window, arguments) === false){ |
---|
904 | return; |
---|
905 | } |
---|
906 | return method.apply(this || window, arguments); |
---|
907 | }; |
---|
908 | } |
---|
909 | }); |
---|
910 | |
---|
911 | /** |
---|
912 | * @class String |
---|
913 | * These functions are available as static methods on the JavaScript String object. |
---|
914 | */ |
---|
915 | Ext.applyIf(String, { |
---|
916 | |
---|
917 | /** |
---|
918 | * Escapes the passed string for ' and \ |
---|
919 | * @param {String} string The string to escape |
---|
920 | * @return {String} The escaped string |
---|
921 | * @static |
---|
922 | */ |
---|
923 | escape : function(string) { |
---|
924 | return string.replace(/('|\\)/g, "\\$1"); |
---|
925 | }, |
---|
926 | |
---|
927 | /** |
---|
928 | * Pads the left side of a string with a specified character. This is especially useful |
---|
929 | * for normalizing number and date strings. Example usage: |
---|
930 | * <pre><code> |
---|
931 | var s = String.leftPad('123', 5, '0'); |
---|
932 | // s now contains the string: '00123' |
---|
933 | </code></pre> |
---|
934 | * @param {String} string The original string |
---|
935 | * @param {Number} size The total length of the output string |
---|
936 | * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ") |
---|
937 | * @return {String} The padded string |
---|
938 | * @static |
---|
939 | */ |
---|
940 | leftPad : function (val, size, ch) { |
---|
941 | var result = new String(val); |
---|
942 | if(!ch) { |
---|
943 | ch = " "; |
---|
944 | } |
---|
945 | while (result.length < size) { |
---|
946 | result = ch + result; |
---|
947 | } |
---|
948 | return result.toString(); |
---|
949 | }, |
---|
950 | |
---|
951 | /** |
---|
952 | * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each |
---|
953 | * token must be unique, and must increment in the format {0}, {1}, etc. Example usage: |
---|
954 | * <pre><code> |
---|
955 | var cls = 'my-class', text = 'Some text'; |
---|
956 | var s = String.format('<div class="{0}">{1}</div>', cls, text); |
---|
957 | // s now contains the string: '<div class="my-class">Some text</div>' |
---|
958 | </code></pre> |
---|
959 | * @param {String} string The tokenized string to be formatted |
---|
960 | * @param {String} value1 The value to replace token {0} |
---|
961 | * @param {String} value2 Etc... |
---|
962 | * @return {String} The formatted string |
---|
963 | * @static |
---|
964 | */ |
---|
965 | format : function(format){ |
---|
966 | var args = Array.prototype.slice.call(arguments, 1); |
---|
967 | return format.replace(/\{(\d+)\}/g, function(m, i){ |
---|
968 | return args[i]; |
---|
969 | }); |
---|
970 | } |
---|
971 | }); |
---|
972 | |
---|
973 | /** |
---|
974 | * Utility function that allows you to easily switch a string between two alternating values. The passed value |
---|
975 | * is compared to the current string, and if they are equal, the other value that was passed in is returned. If |
---|
976 | * they are already different, the first value passed in is returned. Note that this method returns the new value |
---|
977 | * but does not change the current string. |
---|
978 | * <pre><code> |
---|
979 | // alternate sort directions |
---|
980 | sort = sort.toggle('ASC', 'DESC'); |
---|
981 | |
---|
982 | // instead of conditional logic: |
---|
983 | sort = (sort == 'ASC' ? 'DESC' : 'ASC'); |
---|
984 | </code></pre> |
---|
985 | * @param {String} value The value to compare to the current string |
---|
986 | * @param {String} other The new value to use if the string already equals the first value passed in |
---|
987 | * @return {String} The new value |
---|
988 | */ |
---|
989 | String.prototype.toggle = function(value, other){ |
---|
990 | return this == value ? other : value; |
---|
991 | }; |
---|
992 | |
---|
993 | /** |
---|
994 | * Trims whitespace from either end of a string, leaving spaces within the string intact. Example: |
---|
995 | * <pre><code> |
---|
996 | var s = ' foo bar '; |
---|
997 | alert('-' + s + '-'); //alerts "- foo bar -" |
---|
998 | alert('-' + s.trim() + '-'); //alerts "-foo bar-" |
---|
999 | </code></pre> |
---|
1000 | * @return {String} The trimmed string |
---|
1001 | */ |
---|
1002 | String.prototype.trim = function(){ |
---|
1003 | var re = /^\s+|\s+$/g; |
---|
1004 | return function(){ return this.replace(re, ""); }; |
---|
1005 | }(); |
---|
1006 | /** |
---|
1007 | * @class Number |
---|
1008 | */ |
---|
1009 | Ext.applyIf(Number.prototype, { |
---|
1010 | /** |
---|
1011 | * Checks whether or not the current number is within a desired range. If the number is already within the |
---|
1012 | * range it is returned, otherwise the min or max value is returned depending on which side of the range is |
---|
1013 | * exceeded. Note that this method returns the constrained value but does not change the current number. |
---|
1014 | * @param {Number} min The minimum number in the range |
---|
1015 | * @param {Number} max The maximum number in the range |
---|
1016 | * @return {Number} The constrained value if outside the range, otherwise the current value |
---|
1017 | */ |
---|
1018 | constrain : function(min, max){ |
---|
1019 | return Math.min(Math.max(this, min), max); |
---|
1020 | } |
---|
1021 | }); |
---|
1022 | /** |
---|
1023 | * @class Array |
---|
1024 | */ |
---|
1025 | Ext.applyIf(Array.prototype, { |
---|
1026 | /** |
---|
1027 | * Checks whether or not the specified object exists in the array. |
---|
1028 | * @param {Object} o The object to check for |
---|
1029 | * @return {Number} The index of o in the array (or -1 if it is not found) |
---|
1030 | */ |
---|
1031 | indexOf : function(o){ |
---|
1032 | for (var i = 0, len = this.length; i < len; i++){ |
---|
1033 | if(this[i] == o) return i; |
---|
1034 | } |
---|
1035 | return -1; |
---|
1036 | }, |
---|
1037 | |
---|
1038 | /** |
---|
1039 | * Removes the specified object from the array. If the object is not found nothing happens. |
---|
1040 | * @param {Object} o The object to remove |
---|
1041 | * @return {Array} this array |
---|
1042 | */ |
---|
1043 | remove : function(o){ |
---|
1044 | var index = this.indexOf(o); |
---|
1045 | if(index != -1){ |
---|
1046 | this.splice(index, 1); |
---|
1047 | } |
---|
1048 | return this; |
---|
1049 | } |
---|
1050 | }); |
---|
1051 | |
---|
1052 | /** |
---|
1053 | Returns the number of milliseconds between this date and date |
---|
1054 | @param {Date} date (optional) Defaults to now |
---|
1055 | @return {Number} The diff in milliseconds |
---|
1056 | @member Date getElapsed |
---|
1057 | */ |
---|
1058 | Date.prototype.getElapsed = function(date) { |
---|
1059 | return Math.abs((date || new Date()).getTime()-this.getTime()); |
---|
1060 | }; |
---|