Forked mumble-django project from https://bitbucket.org/Svedrin/mumble-django
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2474 lines
86 KiB

  1. /*!
  2. * Ext JS Library 3.2.0
  3. * Copyright(c) 2006-2010 Ext JS, Inc.
  4. * licensing@extjs.com
  5. * http://www.extjs.com/license
  6. */
  7. // for old browsers
  8. window.undefined = window.undefined;
  9. /**
  10. * @class Ext
  11. * Ext core utilities and functions.
  12. * @singleton
  13. */
  14. Ext = {
  15. /**
  16. * The version of the framework
  17. * @type String
  18. */
  19. version : '3.2.0'
  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. // no "this" reference for friendly out of scope calls
  31. if(defaults){
  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. (function(){
  42. var idSeed = 0,
  43. toString = Object.prototype.toString,
  44. ua = navigator.userAgent.toLowerCase(),
  45. check = function(r){
  46. return r.test(ua);
  47. },
  48. DOC = document,
  49. isStrict = DOC.compatMode == "CSS1Compat",
  50. isOpera = check(/opera/),
  51. isChrome = check(/\bchrome\b/),
  52. isWebKit = check(/webkit/),
  53. isSafari = !isChrome && check(/safari/),
  54. isSafari2 = isSafari && check(/applewebkit\/4/), // unique to Safari 2
  55. isSafari3 = isSafari && check(/version\/3/),
  56. isSafari4 = isSafari && check(/version\/4/),
  57. isIE = !isOpera && check(/msie/),
  58. isIE7 = isIE && check(/msie 7/),
  59. isIE8 = isIE && check(/msie 8/),
  60. isIE6 = isIE && !isIE7 && !isIE8,
  61. isGecko = !isWebKit && check(/gecko/),
  62. isGecko2 = isGecko && check(/rv:1\.8/),
  63. isGecko3 = isGecko && check(/rv:1\.9/),
  64. isBorderBox = isIE && !isStrict,
  65. isWindows = check(/windows|win32/),
  66. isMac = check(/macintosh|mac os x/),
  67. isAir = check(/adobeair/),
  68. isLinux = check(/linux/),
  69. isSecure = /^https/i.test(window.location.protocol);
  70. // remove css image flicker
  71. if(isIE6){
  72. try{
  73. DOC.execCommand("BackgroundImageCache", false, true);
  74. }catch(e){}
  75. }
  76. Ext.apply(Ext, {
  77. /**
  78. * URL to a blank file used by Ext when in secure mode for iframe src and onReady src to prevent
  79. * the IE insecure content warning (<tt>'about:blank'</tt>, except for IE in secure mode, which is <tt>'javascript:""'</tt>).
  80. * @type String
  81. */
  82. SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
  83. /**
  84. * True if the browser is in strict (standards-compliant) mode, as opposed to quirks mode
  85. * @type Boolean
  86. */
  87. isStrict : isStrict,
  88. /**
  89. * True if the page is running over SSL
  90. * @type Boolean
  91. */
  92. isSecure : isSecure,
  93. /**
  94. * True when the document is fully initialized and ready for action
  95. * @type Boolean
  96. */
  97. isReady : false,
  98. /**
  99. * True if the {@link Ext.Fx} Class is available
  100. * @type Boolean
  101. * @property enableFx
  102. */
  103. /**
  104. * True to automatically uncache orphaned Ext.Elements periodically (defaults to true)
  105. * @type Boolean
  106. */
  107. enableGarbageCollector : true,
  108. /**
  109. * True to automatically purge event listeners during garbageCollection (defaults to false).
  110. * @type Boolean
  111. */
  112. enableListenerCollection : false,
  113. /**
  114. * EXPERIMENTAL - True to cascade listener removal to child elements when an element is removed.
  115. * Currently not optimized for performance.
  116. * @type Boolean
  117. */
  118. enableNestedListenerRemoval : false,
  119. /**
  120. * Indicates whether to use native browser parsing for JSON methods.
  121. * This option is ignored if the browser does not support native JSON methods.
  122. * <b>Note: Native JSON methods will not work with objects that have functions.
  123. * Also, property names must be quoted, otherwise the data will not parse.</b> (Defaults to false)
  124. * @type Boolean
  125. */
  126. USE_NATIVE_JSON : false,
  127. /**
  128. * Copies all the properties of config to obj if they don't already exist.
  129. * @param {Object} obj The receiver of the properties
  130. * @param {Object} config The source of the properties
  131. * @return {Object} returns obj
  132. */
  133. applyIf : function(o, c){
  134. if(o){
  135. for(var p in c){
  136. if(!Ext.isDefined(o[p])){
  137. o[p] = c[p];
  138. }
  139. }
  140. }
  141. return o;
  142. },
  143. /**
  144. * Generates unique ids. If the element already has an id, it is unchanged
  145. * @param {Mixed} el (optional) The element to generate an id for
  146. * @param {String} prefix (optional) Id prefix (defaults "ext-gen")
  147. * @return {String} The generated Id.
  148. */
  149. id : function(el, prefix){
  150. el = Ext.getDom(el, true) || {};
  151. if (!el.id) {
  152. el.id = (prefix || "ext-gen") + (++idSeed);
  153. }
  154. return el.id;
  155. },
  156. /**
  157. * <p>Extends one class to create a subclass and optionally overrides members with the passed literal. This method
  158. * also adds the function "override()" to the subclass that can be used to override members of the class.</p>
  159. * For example, to create a subclass of Ext GridPanel:
  160. * <pre><code>
  161. MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
  162. constructor: function(config) {
  163. // Create configuration for this Grid.
  164. var store = new Ext.data.Store({...});
  165. var colModel = new Ext.grid.ColumnModel({...});
  166. // Create a new config object containing our computed properties
  167. // *plus* whatever was in the config parameter.
  168. config = Ext.apply({
  169. store: store,
  170. colModel: colModel
  171. }, config);
  172. MyGridPanel.superclass.constructor.call(this, config);
  173. // Your postprocessing here
  174. },
  175. yourMethod: function() {
  176. // etc.
  177. }
  178. });
  179. </code></pre>
  180. *
  181. * <p>This function also supports a 3-argument call in which the subclass's constructor is
  182. * passed as an argument. In this form, the parameters are as follows:</p>
  183. * <div class="mdetail-params"><ul>
  184. * <li><code>subclass</code> : Function <div class="sub-desc">The subclass constructor.</div></li>
  185. * <li><code>superclass</code> : Function <div class="sub-desc">The constructor of class being extended</div></li>
  186. * <li><code>overrides</code> : Object <div class="sub-desc">A literal with members which are copied into the subclass's
  187. * prototype, and are therefore shared among all instances of the new class.</div></li>
  188. * </ul></div>
  189. *
  190. * @param {Function} superclass The constructor of class being extended.
  191. * @param {Object} overrides <p>A literal with members which are copied into the subclass's
  192. * prototype, and are therefore shared between all instances of the new class.</p>
  193. * <p>This may contain a special member named <tt><b>constructor</b></tt>. This is used
  194. * to define the constructor of the new class, and is returned. If this property is
  195. * <i>not</i> specified, a constructor is generated and returned which just calls the
  196. * superclass's constructor passing on its parameters.</p>
  197. * <p><b>It is essential that you call the superclass constructor in any provided constructor. See example code.</b></p>
  198. * @return {Function} The subclass constructor from the <code>overrides</code> parameter, or a generated one if not provided.
  199. */
  200. extend : function(){
  201. // inline overrides
  202. var io = function(o){
  203. for(var m in o){
  204. this[m] = o[m];
  205. }
  206. };
  207. var oc = Object.prototype.constructor;
  208. return function(sb, sp, overrides){
  209. if(Ext.isObject(sp)){
  210. overrides = sp;
  211. sp = sb;
  212. sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
  213. }
  214. var F = function(){},
  215. sbp,
  216. spp = sp.prototype;
  217. F.prototype = spp;
  218. sbp = sb.prototype = new F();
  219. sbp.constructor=sb;
  220. sb.superclass=spp;
  221. if(spp.constructor == oc){
  222. spp.constructor=sp;
  223. }
  224. sb.override = function(o){
  225. Ext.override(sb, o);
  226. };
  227. sbp.superclass = sbp.supr = (function(){
  228. return spp;
  229. });
  230. sbp.override = io;
  231. Ext.override(sb, overrides);
  232. sb.extend = function(o){return Ext.extend(sb, o);};
  233. return sb;
  234. };
  235. }(),
  236. /**
  237. * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
  238. * Usage:<pre><code>
  239. Ext.override(MyClass, {
  240. newMethod1: function(){
  241. // etc.
  242. },
  243. newMethod2: function(foo){
  244. // etc.
  245. }
  246. });
  247. </code></pre>
  248. * @param {Object} origclass The class to override
  249. * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
  250. * containing one or more methods.
  251. * @method override
  252. */
  253. override : function(origclass, overrides){
  254. if(overrides){
  255. var p = origclass.prototype;
  256. Ext.apply(p, overrides);
  257. if(Ext.isIE && overrides.hasOwnProperty('toString')){
  258. p.toString = overrides.toString;
  259. }
  260. }
  261. },
  262. /**
  263. * Creates namespaces to be used for scoping variables and classes so that they are not global.
  264. * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
  265. * <pre><code>
  266. Ext.namespace('Company', 'Company.data');
  267. Ext.namespace('Company.data'); // equivalent and preferable to above syntax
  268. Company.Widget = function() { ... }
  269. Company.data.CustomStore = function(config) { ... }
  270. </code></pre>
  271. * @param {String} namespace1
  272. * @param {String} namespace2
  273. * @param {String} etc
  274. * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
  275. * @method namespace
  276. */
  277. namespace : function(){
  278. var o, d;
  279. Ext.each(arguments, function(v) {
  280. d = v.split(".");
  281. o = window[d[0]] = window[d[0]] || {};
  282. Ext.each(d.slice(1), function(v2){
  283. o = o[v2] = o[v2] || {};
  284. });
  285. });
  286. return o;
  287. },
  288. /**
  289. * 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.
  290. * @param {Object} o
  291. * @param {String} pre (optional) A prefix to add to the url encoded string
  292. * @return {String}
  293. */
  294. urlEncode : function(o, pre){
  295. var empty,
  296. buf = [],
  297. e = encodeURIComponent;
  298. Ext.iterate(o, function(key, item){
  299. empty = Ext.isEmpty(item);
  300. Ext.each(empty ? key : item, function(val){
  301. buf.push('&', e(key), '=', (!Ext.isEmpty(val) && (val != key || !empty)) ? (Ext.isDate(val) ? Ext.encode(val).replace(/"/g, '') : e(val)) : '');
  302. });
  303. });
  304. if(!pre){
  305. buf.shift();
  306. pre = '';
  307. }
  308. return pre + buf.join('');
  309. },
  310. /**
  311. * Takes an encoded URL and and converts it to an object. Example: <pre><code>
  312. Ext.urlDecode("foo=1&bar=2"); // returns {foo: "1", bar: "2"}
  313. Ext.urlDecode("foo=1&bar=2&bar=3&bar=4", false); // returns {foo: "1", bar: ["2", "3", "4"]}
  314. </code></pre>
  315. * @param {String} string
  316. * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
  317. * @return {Object} A literal with members
  318. */
  319. urlDecode : function(string, overwrite){
  320. if(Ext.isEmpty(string)){
  321. return {};
  322. }
  323. var obj = {},
  324. pairs = string.split('&'),
  325. d = decodeURIComponent,
  326. name,
  327. value;
  328. Ext.each(pairs, function(pair) {
  329. pair = pair.split('=');
  330. name = d(pair[0]);
  331. value = d(pair[1]);
  332. obj[name] = overwrite || !obj[name] ? value :
  333. [].concat(obj[name]).concat(value);
  334. });
  335. return obj;
  336. },
  337. /**
  338. * Appends content to the query string of a URL, handling logic for whether to place
  339. * a question mark or ampersand.
  340. * @param {String} url The URL to append to.
  341. * @param {String} s The content to append to the URL.
  342. * @return (String) The resulting URL
  343. */
  344. urlAppend : function(url, s){
  345. if(!Ext.isEmpty(s)){
  346. return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
  347. }
  348. return url;
  349. },
  350. /**
  351. * Converts any iterable (numeric indices and a length property) into a true array
  352. * Don't use this on strings. IE doesn't support "abc"[0] which this implementation depends on.
  353. * For strings, use this instead: "abc".match(/./g) => [a,b,c];
  354. * @param {Iterable} the iterable object to be turned into a true Array.
  355. * @return (Array) array
  356. */
  357. toArray : function(){
  358. return isIE ?
  359. function(a, i, j, res){
  360. res = [];
  361. for(var x = 0, len = a.length; x < len; x++) {
  362. res.push(a[x]);
  363. }
  364. return res.slice(i || 0, j || res.length);
  365. } :
  366. function(a, i, j){
  367. return Array.prototype.slice.call(a, i || 0, j || a.length);
  368. }
  369. }(),
  370. isIterable : function(v){
  371. //check for array or arguments
  372. if(Ext.isArray(v) || v.callee){
  373. return true;
  374. }
  375. //check for node list type
  376. if(/NodeList|HTMLCollection/.test(toString.call(v))){
  377. return true;
  378. }
  379. //NodeList has an item and length property
  380. //IXMLDOMNodeList has nextNode method, needs to be checked first.
  381. return ((typeof v.nextNode != 'undefined' || v.item) && Ext.isNumber(v.length));
  382. },
  383. /**
  384. * Iterates an array calling the supplied function.
  385. * @param {Array/NodeList/Mixed} array The array to be iterated. If this
  386. * argument is not really an array, the supplied function is called once.
  387. * @param {Function} fn The function to be called with each item. If the
  388. * supplied function returns false, iteration stops and this method returns
  389. * the current <code>index</code>. This function is called with
  390. * the following arguments:
  391. * <div class="mdetail-params"><ul>
  392. * <li><code>item</code> : <i>Mixed</i>
  393. * <div class="sub-desc">The item at the current <code>index</code>
  394. * in the passed <code>array</code></div></li>
  395. * <li><code>index</code> : <i>Number</i>
  396. * <div class="sub-desc">The current index within the array</div></li>
  397. * <li><code>allItems</code> : <i>Array</i>
  398. * <div class="sub-desc">The <code>array</code> passed as the first
  399. * argument to <code>Ext.each</code>.</div></li>
  400. * </ul></div>
  401. * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed.
  402. * Defaults to the <code>item</code> at the current <code>index</code>
  403. * within the passed <code>array</code>.
  404. * @return See description for the fn parameter.
  405. */
  406. each : function(array, fn, scope){
  407. if(Ext.isEmpty(array, true)){
  408. return;
  409. }
  410. if(!Ext.isIterable(array) || Ext.isPrimitive(array)){
  411. array = [array];
  412. }
  413. for(var i = 0, len = array.length; i < len; i++){
  414. if(fn.call(scope || array[i], array[i], i, array) === false){
  415. return i;
  416. };
  417. }
  418. },
  419. /**
  420. * Iterates either the elements in an array, or each of the properties in an object.
  421. * <b>Note</b>: If you are only iterating arrays, it is better to call {@link #each}.
  422. * @param {Object/Array} object The object or array to be iterated
  423. * @param {Function} fn The function to be called for each iteration.
  424. * The iteration will stop if the supplied function returns false, or
  425. * all array elements / object properties have been covered. The signature
  426. * varies depending on the type of object being interated:
  427. * <div class="mdetail-params"><ul>
  428. * <li>Arrays : <tt>(Object item, Number index, Array allItems)</tt>
  429. * <div class="sub-desc">
  430. * When iterating an array, the supplied function is called with each item.</div></li>
  431. * <li>Objects : <tt>(String key, Object value, Object)</tt>
  432. * <div class="sub-desc">
  433. * When iterating an object, the supplied function is called with each key-value pair in
  434. * the object, and the iterated object</div></li>
  435. * </ul></div>
  436. * @param {Object} scope The scope (<code>this</code> reference) in which the specified function is executed. Defaults to
  437. * the <code>object</code> being iterated.
  438. */
  439. iterate : function(obj, fn, scope){
  440. if(Ext.isEmpty(obj)){
  441. return;
  442. }
  443. if(Ext.isIterable(obj)){
  444. Ext.each(obj, fn, scope);
  445. return;
  446. }else if(Ext.isObject(obj)){
  447. for(var prop in obj){
  448. if(obj.hasOwnProperty(prop)){
  449. if(fn.call(scope || obj, prop, obj[prop], obj) === false){
  450. return;
  451. };
  452. }
  453. }
  454. }
  455. },
  456. /**
  457. * Return the dom node for the passed String (id), dom node, or Ext.Element.
  458. * Optional 'strict' flag is needed for IE since it can return 'name' and
  459. * 'id' elements by using getElementById.
  460. * Here are some examples:
  461. * <pre><code>
  462. // gets dom node based on id
  463. var elDom = Ext.getDom('elId');
  464. // gets dom node based on the dom node
  465. var elDom1 = Ext.getDom(elDom);
  466. // If we don&#39;t know if we are working with an
  467. // Ext.Element or a dom node use Ext.getDom
  468. function(el){
  469. var dom = Ext.getDom(el);
  470. // do something with the dom node
  471. }
  472. * </code></pre>
  473. * <b>Note</b>: the dom node to be found actually needs to exist (be rendered, etc)
  474. * when this method is called to be successful.
  475. * @param {Mixed} el
  476. * @return HTMLElement
  477. */
  478. getDom : function(el, strict){
  479. if(!el || !DOC){
  480. return null;
  481. }
  482. if (el.dom){
  483. return el.dom;
  484. } else {
  485. if (Ext.isString(el)) {
  486. var e = DOC.getElementById(el);
  487. // IE returns elements with the 'name' and 'id' attribute.
  488. // we do a strict check to return the element with only the id attribute
  489. if (e && isIE && strict) {
  490. if (el == e.getAttribute('id')) {
  491. return e;
  492. } else {
  493. return null;
  494. }
  495. }
  496. return e;
  497. } else {
  498. return el;
  499. }
  500. }
  501. },
  502. /**
  503. * Returns the current document body as an {@link Ext.Element}.
  504. * @return Ext.Element The document body
  505. */
  506. getBody : function(){
  507. return Ext.get(DOC.body || DOC.documentElement);
  508. },
  509. /**
  510. * Removes a DOM node from the document.
  511. */
  512. /**
  513. * <p>Removes this element from the document, removes all DOM event listeners, and deletes the cache reference.
  514. * All DOM event listeners are removed from this element. If {@link Ext#enableNestedListenerRemoval} is
  515. * <code>true</code>, then DOM event listeners are also removed from all child nodes. The body node
  516. * will be ignored if passed in.</p>
  517. * @param {HTMLElement} node The node to remove
  518. */
  519. removeNode : isIE && !isIE8 ? function(){
  520. var d;
  521. return function(n){
  522. if(n && n.tagName != 'BODY'){
  523. (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
  524. d = d || DOC.createElement('div');
  525. d.appendChild(n);
  526. d.innerHTML = '';
  527. delete Ext.elCache[n.id];
  528. }
  529. }
  530. }() : function(n){
  531. if(n && n.parentNode && n.tagName != 'BODY'){
  532. (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n, true) : Ext.EventManager.removeAll(n);
  533. n.parentNode.removeChild(n);
  534. delete Ext.elCache[n.id];
  535. }
  536. },
  537. /**
  538. * <p>Returns true if the passed value is empty.</p>
  539. * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
  540. * <li>null</li>
  541. * <li>undefined</li>
  542. * <li>an empty array</li>
  543. * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
  544. * </ul></div>
  545. * @param {Mixed} value The value to test
  546. * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false)
  547. * @return {Boolean}
  548. */
  549. isEmpty : function(v, allowBlank){
  550. return v === null || v === undefined || ((Ext.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false);
  551. },
  552. /**
  553. * Returns true if the passed value is a JavaScript array, otherwise false.
  554. * @param {Mixed} value The value to test
  555. * @return {Boolean}
  556. */
  557. isArray : function(v){
  558. return toString.apply(v) === '[object Array]';
  559. },
  560. /**
  561. * Returns true if the passed object is a JavaScript date object, otherwise false.
  562. * @param {Object} object The object to test
  563. * @return {Boolean}
  564. */
  565. isDate : function(v){
  566. return toString.apply(v) === '[object Date]';
  567. },
  568. /**
  569. * Returns true if the passed value is a JavaScript Object, otherwise false.
  570. * @param {Mixed} value The value to test
  571. * @return {Boolean}
  572. */
  573. isObject : function(v){
  574. return !!v && Object.prototype.toString.call(v) === '[object Object]';
  575. },
  576. /**
  577. * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
  578. * @param {Mixed} value The value to test
  579. * @return {Boolean}
  580. */
  581. isPrimitive : function(v){
  582. return Ext.isString(v) || Ext.isNumber(v) || Ext.isBoolean(v);
  583. },
  584. /**
  585. * Returns true if the passed value is a JavaScript Function, otherwise false.
  586. * @param {Mixed} value The value to test
  587. * @return {Boolean}
  588. */
  589. isFunction : function(v){
  590. return toString.apply(v) === '[object Function]';
  591. },
  592. /**
  593. * Returns true if the passed value is a number. Returns false for non-finite numbers.
  594. * @param {Mixed} value The value to test
  595. * @return {Boolean}
  596. */
  597. isNumber : function(v){
  598. return typeof v === 'number' && isFinite(v);
  599. },
  600. /**
  601. * Returns true if the passed value is a string.
  602. * @param {Mixed} value The value to test
  603. * @return {Boolean}
  604. */
  605. isString : function(v){
  606. return typeof v === 'string';
  607. },
  608. /**
  609. * Returns true if the passed value is a boolean.
  610. * @param {Mixed} value The value to test
  611. * @return {Boolean}
  612. */
  613. isBoolean : function(v){
  614. return typeof v === 'boolean';
  615. },
  616. /**
  617. * Returns true if the passed value is an HTMLElement
  618. * @param {Mixed} value The value to test
  619. * @return {Boolean}
  620. */
  621. isElement : function(v) {
  622. return v ? !!v.tagName : false;
  623. },
  624. /**
  625. * Returns true if the passed value is not undefined.
  626. * @param {Mixed} value The value to test
  627. * @return {Boolean}
  628. */
  629. isDefined : function(v){
  630. return typeof v !== 'undefined';
  631. },
  632. /**
  633. * True if the detected browser is Opera.
  634. * @type Boolean
  635. */
  636. isOpera : isOpera,
  637. /**
  638. * True if the detected browser uses WebKit.
  639. * @type Boolean
  640. */
  641. isWebKit : isWebKit,
  642. /**
  643. * True if the detected browser is Chrome.
  644. * @type Boolean
  645. */
  646. isChrome : isChrome,
  647. /**
  648. * True if the detected browser is Safari.
  649. * @type Boolean
  650. */
  651. isSafari : isSafari,
  652. /**
  653. * True if the detected browser is Safari 3.x.
  654. * @type Boolean
  655. */
  656. isSafari3 : isSafari3,
  657. /**
  658. * True if the detected browser is Safari 4.x.
  659. * @type Boolean
  660. */
  661. isSafari4 : isSafari4,
  662. /**
  663. * True if the detected browser is Safari 2.x.
  664. * @type Boolean
  665. */
  666. isSafari2 : isSafari2,
  667. /**
  668. * True if the detected browser is Internet Explorer.
  669. * @type Boolean
  670. */
  671. isIE : isIE,
  672. /**
  673. * True if the detected browser is Internet Explorer 6.x.
  674. * @type Boolean
  675. */
  676. isIE6 : isIE6,
  677. /**
  678. * True if the detected browser is Internet Explorer 7.x.
  679. * @type Boolean
  680. */
  681. isIE7 : isIE7,
  682. /**
  683. * True if the detected browser is Internet Explorer 8.x.
  684. * @type Boolean
  685. */
  686. isIE8 : isIE8,
  687. /**
  688. * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
  689. * @type Boolean
  690. */
  691. isGecko : isGecko,
  692. /**
  693. * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x).
  694. * @type Boolean
  695. */
  696. isGecko2 : isGecko2,
  697. /**
  698. * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
  699. * @type Boolean
  700. */
  701. isGecko3 : isGecko3,
  702. /**
  703. * True if the detected browser is Internet Explorer running in non-strict mode.
  704. * @type Boolean
  705. */
  706. isBorderBox : isBorderBox,
  707. /**
  708. * True if the detected platform is Linux.
  709. * @type Boolean
  710. */
  711. isLinux : isLinux,
  712. /**
  713. * True if the detected platform is Windows.
  714. * @type Boolean
  715. */
  716. isWindows : isWindows,
  717. /**
  718. * True if the detected platform is Mac OS.
  719. * @type Boolean
  720. */
  721. isMac : isMac,
  722. /**
  723. * True if the detected platform is Adobe Air.
  724. * @type Boolean
  725. */
  726. isAir : isAir
  727. });
  728. /**
  729. * Creates namespaces to be used for scoping variables and classes so that they are not global.
  730. * Specifying the last node of a namespace implicitly creates all other nodes. Usage:
  731. * <pre><code>
  732. Ext.namespace('Company', 'Company.data');
  733. Ext.namespace('Company.data'); // equivalent and preferable to above syntax
  734. Company.Widget = function() { ... }
  735. Company.data.CustomStore = function(config) { ... }
  736. </code></pre>
  737. * @param {String} namespace1
  738. * @param {String} namespace2
  739. * @param {String} etc
  740. * @return {Object} The namespace object. (If multiple arguments are passed, this will be the last namespace created)
  741. * @method ns
  742. */
  743. Ext.ns = Ext.namespace;
  744. })();
  745. Ext.ns("Ext.util", "Ext.lib", "Ext.data");
  746. Ext.elCache = {};
  747. /**
  748. * @class Function
  749. * These functions are available on every Function object (any JavaScript function).
  750. */
  751. Ext.apply(Function.prototype, {
  752. /**
  753. * Creates an interceptor function. The passed function is called before the original one. If it returns false,
  754. * the original one is not called. The resulting function returns the results of the original function.
  755. * The passed function is called with the parameters of the original function. Example usage:
  756. * <pre><code>
  757. var sayHi = function(name){
  758. alert('Hi, ' + name);
  759. }
  760. sayHi('Fred'); // alerts "Hi, Fred"
  761. // create a new function that validates input without
  762. // directly modifying the original function:
  763. var sayHiToFriend = sayHi.createInterceptor(function(name){
  764. return name == 'Brian';
  765. });
  766. sayHiToFriend('Fred'); // no alert
  767. sayHiToFriend('Brian'); // alerts "Hi, Brian"
  768. </code></pre>
  769. * @param {Function} fcn The function to call before the original
  770. * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
  771. * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
  772. * @return {Function} The new function
  773. */
  774. createInterceptor : function(fcn, scope){
  775. var method = this;
  776. return !Ext.isFunction(fcn) ?
  777. this :
  778. function() {
  779. var me = this,
  780. args = arguments;
  781. fcn.target = me;
  782. fcn.method = method;
  783. return (fcn.apply(scope || me || window, args) !== false) ?
  784. method.apply(me || window, args) :
  785. null;
  786. };
  787. },
  788. /**
  789. * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
  790. * Call directly on any function. Example: <code>myFunction.createCallback(arg1, arg2)</code>
  791. * Will create a function that is bound to those 2 args. <b>If a specific scope is required in the
  792. * callback, use {@link #createDelegate} instead.</b> The function returned by createCallback always
  793. * executes in the window scope.
  794. * <p>This method is required when you want to pass arguments to a callback function. If no arguments
  795. * are needed, you can simply pass a reference to the function as a callback (e.g., callback: myFn).
  796. * However, if you tried to pass a function with arguments (e.g., callback: myFn(arg1, arg2)) the function
  797. * would simply execute immediately when the code is parsed. Example usage:
  798. * <pre><code>
  799. var sayHi = function(name){
  800. alert('Hi, ' + name);
  801. }
  802. // clicking the button alerts "Hi, Fred"
  803. new Ext.Button({
  804. text: 'Say Hi',
  805. renderTo: Ext.getBody(),
  806. handler: sayHi.createCallback('Fred')
  807. });
  808. </code></pre>
  809. * @return {Function} The new function
  810. */
  811. createCallback : function(/*args...*/){
  812. // make args available, in function below
  813. var args = arguments,
  814. method = this;
  815. return function() {
  816. return method.apply(window, args);
  817. };
  818. },
  819. /**
  820. * Creates a delegate (callback) that sets the scope to obj.
  821. * Call directly on any function. Example: <code>this.myFunction.createDelegate(this, [arg1, arg2])</code>
  822. * Will create a function that is automatically scoped to obj so that the <tt>this</tt> variable inside the
  823. * callback points to obj. Example usage:
  824. * <pre><code>
  825. var sayHi = function(name){
  826. // Note this use of "this.text" here. This function expects to
  827. // execute within a scope that contains a text property. In this
  828. // example, the "this" variable is pointing to the btn object that
  829. // was passed in createDelegate below.
  830. alert('Hi, ' + name + '. You clicked the "' + this.text + '" button.');
  831. }
  832. var btn = new Ext.Button({
  833. text: 'Say Hi',
  834. renderTo: Ext.getBody()
  835. });
  836. // This callback will execute in the scope of the
  837. // button instance. Clicking the button alerts
  838. // "Hi, Fred. You clicked the "Say Hi" button."
  839. btn.on('click', sayHi.createDelegate(btn, ['Fred']));
  840. </code></pre>
  841. * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
  842. * <b>If omitted, defaults to the browser window.</b>
  843. * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
  844. * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
  845. * if a number the args are inserted at the specified position
  846. * @return {Function} The new function
  847. */
  848. createDelegate : function(obj, args, appendArgs){
  849. var method = this;
  850. return function() {
  851. var callArgs = args || arguments;
  852. if (appendArgs === true){
  853. callArgs = Array.prototype.slice.call(arguments, 0);
  854. callArgs = callArgs.concat(args);
  855. }else if (Ext.isNumber(appendArgs)){
  856. callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
  857. var applyArgs = [appendArgs, 0].concat(args); // create method call params
  858. Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
  859. }
  860. return method.apply(obj || window, callArgs);
  861. };
  862. },
  863. /**
  864. * Calls this function after the number of millseconds specified, optionally in a specific scope. Example usage:
  865. * <pre><code>
  866. var sayHi = function(name){
  867. alert('Hi, ' + name);
  868. }
  869. // executes immediately:
  870. sayHi('Fred');
  871. // executes after 2 seconds:
  872. sayHi.defer(2000, this, ['Fred']);
  873. // this syntax is sometimes useful for deferring
  874. // execution of an anonymous function:
  875. (function(){
  876. alert('Anonymous');
  877. }).defer(100);
  878. </code></pre>
  879. * @param {Number} millis The number of milliseconds for the setTimeout call (if less than or equal to 0 the function is executed immediately)
  880. * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the function is executed.
  881. * <b>If omitted, defaults to the browser window.</b>
  882. * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
  883. * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
  884. * if a number the args are inserted at the specified position
  885. * @return {Number} The timeout id that can be used with clearTimeout
  886. */
  887. defer : function(millis, obj, args, appendArgs){
  888. var fn = this.createDelegate(obj, args, appendArgs);
  889. if(millis > 0){
  890. return setTimeout(fn, millis);
  891. }
  892. fn();
  893. return 0;
  894. }
  895. });
  896. /**
  897. * @class String
  898. * These functions are available on every String object.
  899. */
  900. Ext.applyIf(String, {
  901. /**
  902. * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
  903. * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
  904. * <pre><code>
  905. var cls = 'my-class', text = 'Some text';
  906. var s = String.format('&lt;div class="{0}">{1}&lt;/div>', cls, text);
  907. // s now contains the string: '&lt;div class="my-class">Some text&lt;/div>'
  908. * </code></pre>
  909. * @param {String} string The tokenized string to be formatted
  910. * @param {String} value1 The value to replace token {0}
  911. * @param {String} value2 Etc...
  912. * @return {String} The formatted string
  913. * @static
  914. */
  915. format : function(format){
  916. var args = Ext.toArray(arguments, 1);
  917. return format.replace(/\{(\d+)\}/g, function(m, i){
  918. return args[i];
  919. });
  920. }
  921. });
  922. /**
  923. * @class Array
  924. */
  925. Ext.applyIf(Array.prototype, {
  926. /**
  927. * Checks whether or not the specified object exists in the array.
  928. * @param {Object} o The object to check for
  929. * @param {Number} from (Optional) The index at which to begin the search
  930. * @return {Number} The index of o in the array (or -1 if it is not found)
  931. */
  932. indexOf : function(o, from){
  933. var len = this.length;
  934. from = from || 0;
  935. from += (from < 0) ? len : 0;
  936. for (; from < len; ++from){
  937. if(this[from] === o){
  938. return from;
  939. }
  940. }
  941. return -1;
  942. },
  943. /**
  944. * Removes the specified object from the array. If the object is not found nothing happens.
  945. * @param {Object} o The object to remove
  946. * @return {Array} this array
  947. */
  948. remove : function(o){
  949. var index = this.indexOf(o);
  950. if(index != -1){
  951. this.splice(index, 1);
  952. }
  953. return this;
  954. }
  955. });
  956. /**
  957. * @class Ext
  958. */
  959. Ext.ns("Ext.grid", "Ext.list", "Ext.dd", "Ext.tree", "Ext.form", "Ext.menu",
  960. "Ext.state", "Ext.layout", "Ext.app", "Ext.ux", "Ext.chart", "Ext.direct");
  961. /**
  962. * Namespace alloted for extensions to the framework.
  963. * @property ux
  964. * @type Object
  965. */
  966. Ext.apply(Ext, function(){
  967. var E = Ext,
  968. idSeed = 0,
  969. scrollWidth = null;
  970. return {
  971. /**
  972. * A reusable empty function
  973. * @property
  974. * @type Function
  975. */
  976. emptyFn : function(){},
  977. /**
  978. * URL to a 1x1 transparent gif image used by Ext to create inline icons with CSS background images.
  979. * In older versions of IE, this defaults to "http://extjs.com/s.gif" and you should change this to a URL on your server.
  980. * For other browsers it uses an inline data URL.
  981. * @type String
  982. */
  983. BLANK_IMAGE_URL : Ext.isIE6 || Ext.isIE7 || Ext.isAir ?
  984. 'http:/' + '/extjs.com/s.gif' :
  985. 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
  986. extendX : function(supr, fn){
  987. return Ext.extend(supr, fn(supr.prototype));
  988. },
  989. /**
  990. * Returns the current HTML document object as an {@link Ext.Element}.
  991. * @return Ext.Element The document
  992. */
  993. getDoc : function(){
  994. return Ext.get(document);
  995. },
  996. /**
  997. * Utility method for validating that a value is numeric, returning the specified default value if it is not.
  998. * @param {Mixed} value Should be a number, but any type will be handled appropriately
  999. * @param {Number} defaultValue The value to return if the original value is non-numeric
  1000. * @return {Number} Value, if numeric, else defaultValue
  1001. */
  1002. num : function(v, defaultValue){
  1003. v = Number(Ext.isEmpty(v) || Ext.isArray(v) || Ext.isBoolean(v) || (Ext.isString(v) && v.trim().length == 0) ? NaN : v);
  1004. return isNaN(v) ? defaultValue : v;
  1005. },
  1006. /**
  1007. * <p>Utility method for returning a default value if the passed value is empty.</p>
  1008. * <p>The value is deemed to be empty if it is<div class="mdetail-params"><ul>
  1009. * <li>null</li>
  1010. * <li>undefined</li>
  1011. * <li>an empty array</li>
  1012. * <li>a zero length string (Unless the <tt>allowBlank</tt> parameter is <tt>true</tt>)</li>
  1013. * </ul></div>
  1014. * @param {Mixed} value The value to test
  1015. * @param {Mixed} defaultValue The value to return if the original value is empty
  1016. * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
  1017. * @return {Mixed} value, if non-empty, else defaultValue
  1018. */
  1019. value : function(v, defaultValue, allowBlank){
  1020. return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
  1021. },
  1022. /**
  1023. * Escapes the passed string for use in a regular expression
  1024. * @param {String} str
  1025. * @return {String}
  1026. */
  1027. escapeRe : function(s) {
  1028. return s.replace(/([-.*+?^${}()|[\]\/\\])/g, "\\$1");
  1029. },
  1030. sequence : function(o, name, fn, scope){
  1031. o[name] = o[name].createSequence(fn, scope);
  1032. },
  1033. /**
  1034. * Applies event listeners to elements by selectors when the document is ready.
  1035. * The event name is specified with an <tt>&#64;</tt> suffix.
  1036. * <pre><code>
  1037. Ext.addBehaviors({
  1038. // add a listener for click on all anchors in element with id foo
  1039. '#foo a&#64;click' : function(e, t){
  1040. // do something
  1041. },
  1042. // add the same listener to multiple selectors (separated by comma BEFORE the &#64;)
  1043. '#foo a, #bar span.some-class&#64;mouseover' : function(){
  1044. // do something
  1045. }
  1046. });
  1047. * </code></pre>
  1048. * @param {Object} obj The list of behaviors to apply
  1049. */
  1050. addBehaviors : function(o){
  1051. if(!Ext.isReady){
  1052. Ext.onReady(function(){
  1053. Ext.addBehaviors(o);
  1054. });
  1055. } else {
  1056. var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
  1057. parts,
  1058. b,
  1059. s;
  1060. for (b in o) {
  1061. if ((parts = b.split('@'))[1]) { // for Object prototype breakers
  1062. s = parts[0];
  1063. if(!cache[s]){
  1064. cache[s] = Ext.select(s);
  1065. }
  1066. cache[s].on(parts[1], o[b]);
  1067. }
  1068. }
  1069. cache = null;
  1070. }
  1071. },
  1072. /**
  1073. * Utility method for getting the width of the browser scrollbar. This can differ depending on
  1074. * operating system settings, such as the theme or font size.
  1075. * @param {Boolean} force (optional) true to force a recalculation of the value.
  1076. * @return {Number} The width of the scrollbar.
  1077. */
  1078. getScrollBarWidth: function(force){
  1079. if(!Ext.isReady){
  1080. return 0;
  1081. }
  1082. if(force === true || scrollWidth === null){
  1083. // Append our div, do our calculation and then remove it
  1084. var div = Ext.getBody().createChild('<div class="x-hide-offsets" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
  1085. child = div.child('div', true);
  1086. var w1 = child.offsetWidth;
  1087. div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
  1088. var w2 = child.offsetWidth;
  1089. div.remove();
  1090. // Need to add 2 to ensure we leave enough space
  1091. scrollWidth = w1 - w2 + 2;
  1092. }
  1093. return scrollWidth;
  1094. },
  1095. // deprecated
  1096. combine : function(){
  1097. var as = arguments, l = as.length, r = [];
  1098. for(var i = 0; i < l; i++){
  1099. var a = as[i];
  1100. if(Ext.isArray(a)){
  1101. r = r.concat(a);
  1102. }else if(a.length !== undefined && !a.substr){
  1103. r = r.concat(Array.prototype.slice.call(a, 0));
  1104. }else{
  1105. r.push(a);
  1106. }
  1107. }
  1108. return r;
  1109. },
  1110. /**
  1111. * Copies a set of named properties fom the source object to the destination object.
  1112. * <p>example:<pre><code>
  1113. ImageComponent = Ext.extend(Ext.BoxComponent, {
  1114. initComponent: function() {
  1115. this.autoEl = { tag: 'img' };
  1116. MyComponent.superclass.initComponent.apply(this, arguments);
  1117. this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
  1118. }
  1119. });
  1120. * </code></pre>
  1121. * @param {Object} dest The destination object.
  1122. * @param {Object} source The source object.
  1123. * @param {Array/String} names Either an Array of property names, or a comma-delimited list
  1124. * of property names to copy.
  1125. * @return {Object} The modified object.
  1126. */
  1127. copyTo : function(dest, source, names){
  1128. if(Ext.isString(names)){
  1129. names = names.split(/[,;\s]/);
  1130. }
  1131. Ext.each(names, function(name){
  1132. if(source.hasOwnProperty(name)){
  1133. dest[name] = source[name];
  1134. }
  1135. }, this);
  1136. return dest;
  1137. },
  1138. /**
  1139. * Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
  1140. * DOM (if applicable) and calling their destroy functions (if available). This method is primarily
  1141. * intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
  1142. * {@link Ext.util.Observable} can be passed in. Any number of elements and/or components can be
  1143. * passed into this function in a single call as separate arguments.
  1144. * @param {Mixed} arg1 An {@link Ext.Element}, {@link Ext.Component}, or an Array of either of these to destroy
  1145. * @param {Mixed} arg2 (optional)
  1146. * @param {Mixed} etc... (optional)
  1147. */
  1148. destroy : function(){
  1149. Ext.each(arguments, function(arg){
  1150. if(arg){
  1151. if(Ext.isArray(arg)){
  1152. this.destroy.apply(this, arg);
  1153. }else if(Ext.isFunction(arg.destroy)){
  1154. arg.destroy();
  1155. }else if(arg.dom){
  1156. arg.remove();
  1157. }
  1158. }
  1159. }, this);
  1160. },
  1161. /**
  1162. * Attempts to destroy and then remove a set of named properties of the passed object.
  1163. * @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
  1164. * @param {Mixed} arg1 The name of the property to destroy and remove from the object.
  1165. * @param {Mixed} etc... More property names to destroy and remove.
  1166. */
  1167. destroyMembers : function(o, arg1, arg2, etc){
  1168. for(var i = 1, a = arguments, len = a.length; i < len; i++) {
  1169. Ext.destroy(o[a[i]]);
  1170. delete o[a[i]];
  1171. }
  1172. },
  1173. /**
  1174. * Creates a copy of the passed Array with falsy values removed.
  1175. * @param {Array/NodeList} arr The Array from which to remove falsy values.
  1176. * @return {Array} The new, compressed Array.
  1177. */
  1178. clean : function(arr){
  1179. var ret = [];
  1180. Ext.each(arr, function(v){
  1181. if(!!v){
  1182. ret.push(v);
  1183. }
  1184. });
  1185. return ret;
  1186. },
  1187. /**
  1188. * Creates a copy of the passed Array, filtered to contain only unique values.
  1189. * @param {Array} arr The Array to filter
  1190. * @return {Array} The new Array containing unique values.
  1191. */
  1192. unique : function(arr){
  1193. var ret = [],
  1194. collect = {};
  1195. Ext.each(arr, function(v) {
  1196. if(!collect[v]){
  1197. ret.push(v);
  1198. }
  1199. collect[v] = true;
  1200. });
  1201. return ret;
  1202. },
  1203. /**
  1204. * Recursively flattens into 1-d Array. Injects Arrays inline.
  1205. * @param {Array} arr The array to flatten
  1206. * @return {Array} The new, flattened array.
  1207. */
  1208. flatten : function(arr){
  1209. var worker = [];
  1210. function rFlatten(a) {
  1211. Ext.each(a, function(v) {
  1212. if(Ext.isArray(v)){
  1213. rFlatten(v);
  1214. }else{
  1215. worker.push(v);
  1216. }
  1217. });
  1218. return worker;
  1219. }
  1220. return rFlatten(arr);
  1221. },
  1222. /**
  1223. * Returns the minimum value in the Array.
  1224. * @param {Array|NodeList} arr The Array from which to select the minimum value.
  1225. * @param {Function} comp (optional) a function to perform the comparision which determines minimization.
  1226. * If omitted the "<" operator will be used. Note: gt = 1; eq = 0; lt = -1
  1227. * @return {Object} The minimum value in the Array.
  1228. */
  1229. min : function(arr, comp){
  1230. var ret = arr[0];
  1231. comp = comp || function(a,b){ return a < b ? -1 : 1; };
  1232. Ext.each(arr, function(v) {
  1233. ret = comp(ret, v) == -1 ? ret : v;
  1234. });
  1235. return ret;
  1236. },
  1237. /**
  1238. * Returns the maximum value in the Array
  1239. * @param {Array|NodeList} arr The Array from which to select the maximum value.
  1240. * @param {Function} comp (optional) a function to perform the comparision which determines maximization.
  1241. * If omitted the ">" operator will be used. Note: gt = 1; eq = 0; lt = -1
  1242. * @return {Object} The maximum value in the Array.
  1243. */
  1244. max : function(arr, comp){
  1245. var ret = arr[0];
  1246. comp = comp || function(a,b){ return a > b ? 1 : -1; };
  1247. Ext.each(arr, function(v) {
  1248. ret = comp(ret, v) == 1 ? ret : v;
  1249. });
  1250. return ret;
  1251. },
  1252. /**
  1253. * Calculates the mean of the Array
  1254. * @param {Array} arr The Array to calculate the mean value of.
  1255. * @return {Number} The mean.
  1256. */
  1257. mean : function(arr){
  1258. return arr.length > 0 ? Ext.sum(arr) / arr.length : undefined;
  1259. },
  1260. /**
  1261. * Calculates the sum of the Array
  1262. * @param {Array} arr The Array to calculate the sum value of.
  1263. * @return {Number} The sum.
  1264. */
  1265. sum : function(arr){
  1266. var ret = 0;
  1267. Ext.each(arr, function(v) {
  1268. ret += v;
  1269. });
  1270. return ret;
  1271. },
  1272. /**
  1273. * Partitions the set into two sets: a true set and a false set.
  1274. * Example:
  1275. * Example2:
  1276. * <pre><code>
  1277. // Example 1:
  1278. Ext.partition([true, false, true, true, false]); // [[true, true, true], [false, false]]
  1279. // Example 2:
  1280. Ext.partition(
  1281. Ext.query("p"),
  1282. function(val){
  1283. return val.className == "class1"
  1284. }
  1285. );
  1286. // true are those paragraph elements with a className of "class1",
  1287. // false set are those that do not have that className.
  1288. * </code></pre>
  1289. * @param {Array|NodeList} arr The array to partition
  1290. * @param {Function} truth (optional) a function to determine truth. If this is omitted the element
  1291. * itself must be able to be evaluated for its truthfulness.
  1292. * @return {Array} [true<Array>,false<Array>]
  1293. */
  1294. partition : function(arr, truth){
  1295. var ret = [[],[]];
  1296. Ext.each(arr, function(v, i, a) {
  1297. ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
  1298. });
  1299. return ret;
  1300. },
  1301. /**
  1302. * Invokes a method on each item in an Array.
  1303. * <pre><code>
  1304. // Example:
  1305. Ext.invoke(Ext.query("p"), "getAttribute", "id");
  1306. // [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
  1307. * </code></pre>
  1308. * @param {Array|NodeList} arr The Array of items to invoke the method on.
  1309. * @param {String} methodName The method name to invoke.
  1310. * @param {...*} args Arguments to send into the method invocation.
  1311. * @return {Array} The results of invoking the method on each item in the array.
  1312. */
  1313. invoke : function(arr, methodName){
  1314. var ret = [],
  1315. args = Array.prototype.slice.call(arguments, 2);
  1316. Ext.each(arr, function(v,i) {
  1317. if (v && Ext.isFunction(v[methodName])) {
  1318. ret.push(v[methodName].apply(v, args));
  1319. } else {
  1320. ret.push(undefined);
  1321. }
  1322. });
  1323. return ret;
  1324. },
  1325. /**
  1326. * Plucks the value of a property from each item in the Array
  1327. * <pre><code>
  1328. // Example:
  1329. Ext.pluck(Ext.query("p"), "className"); // [el1.className, el2.className, ..., elN.className]
  1330. * </code></pre>
  1331. * @param {Array|NodeList} arr The Array of items to pluck the value from.
  1332. * @param {String} prop The property name to pluck from each element.
  1333. * @return {Array} The value from each item in the Array.
  1334. */
  1335. pluck : function(arr, prop){
  1336. var ret = [];
  1337. Ext.each(arr, function(v) {
  1338. ret.push( v[prop] );
  1339. });
  1340. return ret;
  1341. },
  1342. /**
  1343. * <p>Zips N sets together.</p>
  1344. * <pre><code>
  1345. // Example 1:
  1346. Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
  1347. // Example 2:
  1348. Ext.zip(
  1349. [ "+", "-", "+"],
  1350. [ 12, 10, 22],
  1351. [ 43, 15, 96],
  1352. function(a, b, c){
  1353. return "$" + a + "" + b + "." + c
  1354. }
  1355. ); // ["$+12.43", "$-10.15", "$+22.96"]
  1356. * </code></pre>
  1357. * @param {Arrays|NodeLists} arr This argument may be repeated. Array(s) to contribute values.
  1358. * @param {Function} zipper (optional) The last item in the argument list. This will drive how the items are zipped together.
  1359. * @return {Array} The zipped set.
  1360. */
  1361. zip : function(){
  1362. var parts = Ext.partition(arguments, function( val ){ return !Ext.isFunction(val); }),
  1363. arrs = parts[0],
  1364. fn = parts[1][0],
  1365. len = Ext.max(Ext.pluck(arrs, "length")),
  1366. ret = [];
  1367. for (var i = 0; i < len; i++) {
  1368. ret[i] = [];
  1369. if(fn){
  1370. ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
  1371. }else{
  1372. for (var j = 0, aLen = arrs.length; j < aLen; j++){
  1373. ret[i].push( arrs[j][i] );
  1374. }
  1375. }
  1376. }
  1377. return ret;
  1378. },
  1379. /**
  1380. * This is shorthand reference to {@link Ext.ComponentMgr#get}.
  1381. * Looks up an existing {@link Ext.Component Component} by {@link Ext.Component#id id}
  1382. * @param {String} id The component {@link Ext.Component#id id}
  1383. * @return Ext.Component The Component, <tt>undefined</tt> if not found, or <tt>null</tt> if a
  1384. * Class was found.
  1385. */
  1386. getCmp : function(id){
  1387. return Ext.ComponentMgr.get(id);
  1388. },
  1389. /**
  1390. * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
  1391. * you may want to set this to true.
  1392. * @type Boolean
  1393. */
  1394. useShims: E.isIE6 || (E.isMac && E.isGecko2),
  1395. // inpired by a similar function in mootools library
  1396. /**
  1397. * Returns the type of object that is passed in. If the object passed in is null or undefined it
  1398. * return false otherwise it returns one of the following values:<div class="mdetail-params"><ul>
  1399. * <li><b>string</b>: If the object passed is a string</li>
  1400. * <li><b>number</b>: If the object passed is a number</li>
  1401. * <li><b>boolean</b>: If the object passed is a boolean value</li>
  1402. * <li><b>date</b>: If the object passed is a Date object</li>
  1403. * <li><b>function</b>: If the object passed is a function reference</li>
  1404. * <li><b>object</b>: If the object passed is an object</li>
  1405. * <li><b>array</b>: If the object passed is an array</li>
  1406. * <li><b>regexp</b>: If the object passed is a regular expression</li>
  1407. * <li><b>element</b>: If the object passed is a DOM Element</li>
  1408. * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
  1409. * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
  1410. * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
  1411. * </ul></div>
  1412. * @param {Mixed} object
  1413. * @return {String}
  1414. */
  1415. type : function(o){
  1416. if(o === undefined || o === null){
  1417. return false;
  1418. }
  1419. if(o.htmlElement){
  1420. return 'element';
  1421. }
  1422. var t = typeof o;
  1423. if(t == 'object' && o.nodeName) {
  1424. switch(o.nodeType) {
  1425. case 1: return 'element';
  1426. case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
  1427. }
  1428. }
  1429. if(t == 'object' || t == 'function') {
  1430. switch(o.constructor) {
  1431. case Array: return 'array';
  1432. case RegExp: return 'regexp';
  1433. case Date: return 'date';
  1434. }
  1435. if(Ext.isNumber(o.length) && Ext.isFunction(o.item)) {
  1436. return 'nodelist';
  1437. }
  1438. }
  1439. return t;
  1440. },
  1441. intercept : function(o, name, fn, scope){
  1442. o[name] = o[name].createInterceptor(fn, scope);
  1443. },
  1444. // internal
  1445. callback : function(cb, scope, args, delay){
  1446. if(Ext.isFunction(cb)){
  1447. if(delay){
  1448. cb.defer(delay, scope, args || []);
  1449. }else{
  1450. cb.apply(scope, args || []);
  1451. }
  1452. }
  1453. }
  1454. };
  1455. }());
  1456. /**
  1457. * @class Function
  1458. * These functions are available on every Function object (any JavaScript function).
  1459. */
  1460. Ext.apply(Function.prototype, {
  1461. /**
  1462. * Create a combined function call sequence of the original function + the passed function.
  1463. * The resulting function returns the results of the original function.
  1464. * The passed fcn is called with the parameters of the original function. Example usage:
  1465. * <pre><code>
  1466. var sayHi = function(name){
  1467. alert('Hi, ' + name);
  1468. }
  1469. sayHi('Fred'); // alerts "Hi, Fred"
  1470. var sayGoodbye = sayHi.createSequence(function(name){
  1471. alert('Bye, ' + name);
  1472. });
  1473. sayGoodbye('Fred'); // both alerts show
  1474. </code></pre>
  1475. * @param {Function} fcn The function to sequence
  1476. * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the passed function is executed.
  1477. * <b>If omitted, defaults to the scope in which the original function is called or the browser window.</b>
  1478. * @return {Function} The new function
  1479. */
  1480. createSequence : function(fcn, scope){
  1481. var method = this;
  1482. return !Ext.isFunction(fcn) ?
  1483. this :
  1484. function(){
  1485. var retval = method.apply(this || window, arguments);
  1486. fcn.apply(scope || this || window, arguments);
  1487. return retval;
  1488. };
  1489. }
  1490. });
  1491. /**
  1492. * @class String
  1493. * These functions are available as static methods on the JavaScript String object.
  1494. */
  1495. Ext.applyIf(String, {
  1496. /**
  1497. * Escapes the passed string for ' and \
  1498. * @param {String} string The string to escape
  1499. * @return {String} The escaped string
  1500. * @static
  1501. */
  1502. escape : function(string) {
  1503. return string.replace(/('|\\)/g, "\\$1");
  1504. },
  1505. /**
  1506. * Pads the left side of a string with a specified character. This is especially useful
  1507. * for normalizing number and date strings. Example usage:
  1508. * <pre><code>
  1509. var s = String.leftPad('123', 5, '0');
  1510. // s now contains the string: '00123'
  1511. * </code></pre>
  1512. * @param {String} string The original string
  1513. * @param {Number} size The total length of the output string
  1514. * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
  1515. * @return {String} The padded string
  1516. * @static
  1517. */
  1518. leftPad : function (val, size, ch) {
  1519. var result = String(val);
  1520. if(!ch) {
  1521. ch = " ";
  1522. }
  1523. while (result.length < size) {
  1524. result = ch + result;
  1525. }
  1526. return result;
  1527. }
  1528. });
  1529. /**
  1530. * Utility function that allows you to easily switch a string between two alternating values. The passed value
  1531. * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
  1532. * they are already different, the first value passed in is returned. Note that this method returns the new value
  1533. * but does not change the current string.
  1534. * <pre><code>
  1535. // alternate sort directions
  1536. sort = sort.toggle('ASC', 'DESC');
  1537. // instead of conditional logic:
  1538. sort = (sort == 'ASC' ? 'DESC' : 'ASC');
  1539. </code></pre>
  1540. * @param {String} value The value to compare to the current string
  1541. * @param {String} other The new value to use if the string already equals the first value passed in
  1542. * @return {String} The new value
  1543. */
  1544. String.prototype.toggle = function(value, other){
  1545. return this == value ? other : value;
  1546. };
  1547. /**
  1548. * Trims whitespace from either end of a string, leaving spaces within the string intact. Example:
  1549. * <pre><code>
  1550. var s = ' foo bar ';
  1551. alert('-' + s + '-'); //alerts "- foo bar -"
  1552. alert('-' + s.trim() + '-'); //alerts "-foo bar-"
  1553. </code></pre>
  1554. * @return {String} The trimmed string
  1555. */
  1556. String.prototype.trim = function(){
  1557. var re = /^\s+|\s+$/g;
  1558. return function(){ return this.replace(re, ""); };
  1559. }();
  1560. // here to prevent dependency on Date.js
  1561. /**
  1562. Returns the number of milliseconds between this date and date
  1563. @param {Date} date (optional) Defaults to now
  1564. @return {Number} The diff in milliseconds
  1565. @member Date getElapsed
  1566. */
  1567. Date.prototype.getElapsed = function(date) {
  1568. return Math.abs((date || new Date()).getTime()-this.getTime());
  1569. };
  1570. /**
  1571. * @class Number
  1572. */
  1573. Ext.applyIf(Number.prototype, {
  1574. /**
  1575. * Checks whether or not the current number is within a desired range. If the number is already within the
  1576. * range it is returned, otherwise the min or max value is returned depending on which side of the range is
  1577. * exceeded. Note that this method returns the constrained value but does not change the current number.
  1578. * @param {Number} min The minimum number in the range
  1579. * @param {Number} max The maximum number in the range
  1580. * @return {Number} The constrained value if outside the range, otherwise the current value
  1581. */
  1582. constrain : function(min, max){
  1583. return Math.min(Math.max(this, min), max);
  1584. }
  1585. });
  1586. /**
  1587. * @class Ext.util.TaskRunner
  1588. * Provides the ability to execute one or more arbitrary tasks in a multithreaded
  1589. * manner. Generally, you can use the singleton {@link Ext.TaskMgr} instead, but
  1590. * if needed, you can create separate instances of TaskRunner. Any number of
  1591. * separate tasks can be started at any time and will run independently of each
  1592. * other. Example usage:
  1593. * <pre><code>
  1594. // Start a simple clock task that updates a div once per second
  1595. var updateClock = function(){
  1596. Ext.fly('clock').update(new Date().format('g:i:s A'));
  1597. }
  1598. var task = {
  1599. run: updateClock,
  1600. interval: 1000 //1 second
  1601. }
  1602. var runner = new Ext.util.TaskRunner();
  1603. runner.start(task);
  1604. // equivalent using TaskMgr
  1605. Ext.TaskMgr.start({
  1606. run: updateClock,
  1607. interval: 1000
  1608. });
  1609. * </code></pre>
  1610. * <p>See the {@link #start} method for details about how to configure a task object.</p>
  1611. * Also see {@link Ext.util.DelayedTask}.
  1612. *
  1613. * @constructor
  1614. * @param {Number} interval (optional) The minimum precision in milliseconds supported by this TaskRunner instance
  1615. * (defaults to 10)
  1616. */
  1617. Ext.util.TaskRunner = function(interval){
  1618. interval = interval || 10;
  1619. var tasks = [],
  1620. removeQueue = [],
  1621. id = 0,
  1622. running = false,
  1623. // private
  1624. stopThread = function(){
  1625. running = false;
  1626. clearInterval(id);
  1627. id = 0;
  1628. },
  1629. // private
  1630. startThread = function(){
  1631. if(!running){
  1632. running = true;
  1633. id = setInterval(runTasks, interval);
  1634. }
  1635. },
  1636. // private
  1637. removeTask = function(t){
  1638. removeQueue.push(t);
  1639. if(t.onStop){
  1640. t.onStop.apply(t.scope || t);
  1641. }
  1642. },
  1643. // private
  1644. runTasks = function(){
  1645. var rqLen = removeQueue.length,
  1646. now = new Date().getTime();
  1647. if(rqLen > 0){
  1648. for(var i = 0; i < rqLen; i++){
  1649. tasks.remove(removeQueue[i]);
  1650. }
  1651. removeQueue = [];
  1652. if(tasks.length < 1){
  1653. stopThread();
  1654. return;
  1655. }
  1656. }
  1657. for(var i = 0, t, itime, rt, len = tasks.length; i < len; ++i){
  1658. t = tasks[i];
  1659. itime = now - t.taskRunTime;
  1660. if(t.interval <= itime){
  1661. rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
  1662. t.taskRunTime = now;
  1663. if(rt === false || t.taskRunCount === t.repeat){
  1664. removeTask(t);
  1665. return;
  1666. }
  1667. }
  1668. if(t.duration && t.duration <= (now - t.taskStartTime)){
  1669. removeTask(t);
  1670. }
  1671. }
  1672. };
  1673. /**
  1674. * Starts a new task.
  1675. * @method start
  1676. * @param {Object} task <p>A config object that supports the following properties:<ul>
  1677. * <li><code>run</code> : Function<div class="sub-desc"><p>The function to execute each time the task is invoked. The
  1678. * function will be called at each interval and passed the <code>args</code> argument if specified, and the
  1679. * current invocation count if not.</p>
  1680. * <p>If a particular scope (<code>this</code> reference) is required, be sure to specify it using the <code>scope</code> argument.</p>
  1681. * <p>Return <code>false</code> from this function to terminate the task.</p></div></li>
  1682. * <li><code>interval</code> : Number<div class="sub-desc">The frequency in milliseconds with which the task
  1683. * should be invoked.</div></li>
  1684. * <li><code>args</code> : Array<div class="sub-desc">(optional) An array of arguments to be passed to the function
  1685. * specified by <code>run</code>. If not specified, the current invocation count is passed.</div></li>
  1686. * <li><code>scope</code> : Object<div class="sub-desc">(optional) The scope (<tt>this</tt> reference) in which to execute the
  1687. * <code>run</code> function. Defaults to the task config object.</div></li>
  1688. * <li><code>duration</code> : Number<div class="sub-desc">(optional) The length of time in milliseconds to invoke
  1689. * the task before stopping automatically (defaults to indefinite).</div></li>
  1690. * <li><code>repeat</code> : Number<div class="sub-desc">(optional) The number of times to invoke the task before
  1691. * stopping automatically (defaults to indefinite).</div></li>
  1692. * </ul></p>
  1693. * <p>Before each invocation, Ext injects the property <code>taskRunCount</code> into the task object so
  1694. * that calculations based on the repeat count can be performed.</p>
  1695. * @return {Object} The task
  1696. */
  1697. this.start = function(task){
  1698. tasks.push(task);
  1699. task.taskStartTime = new Date().getTime();
  1700. task.taskRunTime = 0;
  1701. task.taskRunCount = 0;
  1702. startThread();
  1703. return task;
  1704. };
  1705. /**
  1706. * Stops an existing running task.
  1707. * @method stop
  1708. * @param {Object} task The task to stop
  1709. * @return {Object} The task
  1710. */
  1711. this.stop = function(task){
  1712. removeTask(task);
  1713. return task;
  1714. };
  1715. /**
  1716. * Stops all tasks that are currently running.
  1717. * @method stopAll
  1718. */
  1719. this.stopAll = function(){
  1720. stopThread();
  1721. for(var i = 0, len = tasks.length; i < len; i++){
  1722. if(tasks[i].onStop){
  1723. tasks[i].onStop();
  1724. }
  1725. }
  1726. tasks = [];
  1727. removeQueue = [];
  1728. };
  1729. };
  1730. /**
  1731. * @class Ext.TaskMgr
  1732. * @extends Ext.util.TaskRunner
  1733. * A static {@link Ext.util.TaskRunner} instance that can be used to start and stop arbitrary tasks. See
  1734. * {@link Ext.util.TaskRunner} for supported methods and task config properties.
  1735. * <pre><code>
  1736. // Start a simple clock task that updates a div once per second
  1737. var task = {
  1738. run: function(){
  1739. Ext.fly('clock').update(new Date().format('g:i:s A'));
  1740. },
  1741. interval: 1000 //1 second
  1742. }
  1743. Ext.TaskMgr.start(task);
  1744. </code></pre>
  1745. * <p>See the {@link #start} method for details about how to configure a task object.</p>
  1746. * @singleton
  1747. */
  1748. Ext.TaskMgr = new Ext.util.TaskRunner();(function(){
  1749. var libFlyweight,
  1750. version = Prototype.Version.split('.'),
  1751. mouseEnterSupported = (parseInt(version[0]) >= 2) || (parseInt(version[1]) >= 7) || (parseInt(version[2]) >= 1),
  1752. mouseCache = {},
  1753. elContains = function(parent, child) {
  1754. if(parent && parent.firstChild){
  1755. while(child) {
  1756. if(child === parent) {
  1757. return true;
  1758. }
  1759. child = child.parentNode;
  1760. if(child && (child.nodeType != 1)) {
  1761. child = null;
  1762. }
  1763. }
  1764. }
  1765. return false;
  1766. },
  1767. checkRelatedTarget = function(e) {
  1768. return !elContains(e.currentTarget, Ext.lib.Event.getRelatedTarget(e));
  1769. };
  1770. Ext.lib.Dom = {
  1771. getViewWidth : function(full){
  1772. return full ? this.getDocumentWidth() : this.getViewportWidth();
  1773. },
  1774. getViewHeight : function(full){
  1775. return full ? this.getDocumentHeight() : this.getViewportHeight();
  1776. },
  1777. getDocumentHeight: function() { // missing from prototype?
  1778. var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
  1779. return Math.max(scrollHeight, this.getViewportHeight());
  1780. },
  1781. getDocumentWidth: function() { // missing from prototype?
  1782. var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
  1783. return Math.max(scrollWidth, this.getViewportWidth());
  1784. },
  1785. getViewportHeight: function() { // missing from prototype?
  1786. var height = self.innerHeight;
  1787. var mode = document.compatMode;
  1788. if ( (mode || Ext.isIE) && !Ext.isOpera ) {
  1789. height = (mode == "CSS1Compat") ?
  1790. document.documentElement.clientHeight : // Standards
  1791. document.body.clientHeight; // Quirks
  1792. }
  1793. return height;
  1794. },
  1795. getViewportWidth: function() { // missing from prototype?
  1796. var width = self.innerWidth; // Safari
  1797. var mode = document.compatMode;
  1798. if (mode || Ext.isIE) { // IE, Gecko, Opera
  1799. width = (mode == "CSS1Compat") ?
  1800. document.documentElement.clientWidth : // Standards
  1801. document.body.clientWidth; // Quirks
  1802. }
  1803. return width;
  1804. },
  1805. isAncestor : function(p, c){ // missing from prototype?
  1806. var ret = false;
  1807. p = Ext.getDom(p);
  1808. c = Ext.getDom(c);
  1809. if (p && c) {
  1810. if (p.contains) {
  1811. return p.contains(c);
  1812. } else if (p.compareDocumentPosition) {
  1813. return !!(p.compareDocumentPosition(c) & 16);
  1814. } else {
  1815. while (c = c.parentNode) {
  1816. ret = c == p || ret;
  1817. }
  1818. }
  1819. }
  1820. return ret;
  1821. },
  1822. getRegion : function(el){
  1823. return Ext.lib.Region.getRegion(el);
  1824. },
  1825. getY : function(el){
  1826. return this.getXY(el)[1];
  1827. },
  1828. getX : function(el){
  1829. return this.getXY(el)[0];
  1830. },
  1831. getXY : function(el){ // this initially used Position.cumulativeOffset but it is not accurate enough
  1832. var p, pe, b, scroll, bd = (document.body || document.documentElement);
  1833. el = Ext.getDom(el);
  1834. if(el == bd){
  1835. return [0, 0];
  1836. }
  1837. if (el.getBoundingClientRect) {
  1838. b = el.getBoundingClientRect();
  1839. scroll = fly(document).getScroll();
  1840. return [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
  1841. }
  1842. var x = 0, y = 0;
  1843. p = el;
  1844. var hasAbsolute = fly(el).getStyle("position") == "absolute";
  1845. while (p) {
  1846. x += p.offsetLeft;
  1847. y += p.offsetTop;
  1848. if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
  1849. hasAbsolute = true;
  1850. }
  1851. if (Ext.isGecko) {
  1852. pe = fly(p);
  1853. var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
  1854. var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
  1855. x += bl;
  1856. y += bt;
  1857. if (p != el && pe.getStyle('overflow') != 'visible') {
  1858. x += bl;
  1859. y += bt;
  1860. }
  1861. }
  1862. p = p.offsetParent;
  1863. }
  1864. if (Ext.isSafari && hasAbsolute) {
  1865. x -= bd.offsetLeft;
  1866. y -= bd.offsetTop;
  1867. }
  1868. if (Ext.isGecko && !hasAbsolute) {
  1869. var dbd = fly(bd);
  1870. x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
  1871. y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
  1872. }
  1873. p = el.parentNode;
  1874. while (p && p != bd) {
  1875. if (!Ext.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
  1876. x -= p.scrollLeft;
  1877. y -= p.scrollTop;
  1878. }
  1879. p = p.parentNode;
  1880. }
  1881. return [x, y];
  1882. },
  1883. setXY : function(el, xy){ // this initially used Position.cumulativeOffset but it is not accurate enough
  1884. el = Ext.fly(el, '_setXY');
  1885. el.position();
  1886. var pts = el.translatePoints(xy);
  1887. if(xy[0] !== false){
  1888. el.dom.style.left = pts.left + "px";
  1889. }
  1890. if(xy[1] !== false){
  1891. el.dom.style.top = pts.top + "px";
  1892. }
  1893. },
  1894. setX : function(el, x){
  1895. this.setXY(el, [x, false]);
  1896. },
  1897. setY : function(el, y){
  1898. this.setXY(el, [false, y]);
  1899. }
  1900. };
  1901. Ext.lib.Event = {
  1902. getPageX : function(e){
  1903. return Event.pointerX(e.browserEvent || e);
  1904. },
  1905. getPageY : function(e){
  1906. return Event.pointerY(e.browserEvent || e);
  1907. },
  1908. getXY : function(e){
  1909. e = e.browserEvent || e;
  1910. return [Event.pointerX(e), Event.pointerY(e)];
  1911. },
  1912. getTarget : function(e){
  1913. return Event.element(e.browserEvent || e);
  1914. },
  1915. resolveTextNode: Ext.isGecko ? function(node){
  1916. if(!node){
  1917. return;
  1918. }
  1919. var s = HTMLElement.prototype.toString.call(node);
  1920. if(s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]'){
  1921. return;
  1922. }
  1923. return node.nodeType == 3 ? node.parentNode : node;
  1924. } : function(node){
  1925. return node && node.nodeType == 3 ? node.parentNode : node;
  1926. },
  1927. getRelatedTarget: function(ev) { // missing from prototype?
  1928. ev = ev.browserEvent || ev;
  1929. var t = ev.relatedTarget;
  1930. if (!t) {
  1931. if (ev.type == "mouseout") {
  1932. t = ev.toElement;
  1933. } else if (ev.type == "mouseover") {
  1934. t = ev.fromElement;
  1935. }
  1936. }
  1937. return this.resolveTextNode(t);
  1938. },
  1939. on : function(el, eventName, fn){
  1940. if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
  1941. var item = mouseCache[el.id] || (mouseCache[el.id] = {});
  1942. item[eventName] = fn;
  1943. fn = fn.createInterceptor(checkRelatedTarget);
  1944. eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
  1945. }
  1946. Event.observe(el, eventName, fn, false);
  1947. },
  1948. un : function(el, eventName, fn){
  1949. if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
  1950. var item = mouseCache[el.id],
  1951. ev = item && item[eventName];
  1952. if(ev){
  1953. fn = ev.fn;
  1954. delete item[eventName];
  1955. eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
  1956. }
  1957. }
  1958. Event.stopObserving(el, eventName, fn, false);
  1959. },
  1960. purgeElement : function(el){
  1961. // no equiv?
  1962. },
  1963. preventDefault : function(e){ // missing from prototype?
  1964. e = e.browserEvent || e;
  1965. if(e.preventDefault) {
  1966. e.preventDefault();
  1967. } else {
  1968. e.returnValue = false;
  1969. }
  1970. },
  1971. stopPropagation : function(e){ // missing from prototype?
  1972. e = e.browserEvent || e;
  1973. if(e.stopPropagation) {
  1974. e.stopPropagation();
  1975. } else {
  1976. e.cancelBubble = true;
  1977. }
  1978. },
  1979. stopEvent : function(e){
  1980. Event.stop(e.browserEvent || e);
  1981. },
  1982. onAvailable : function(id, fn, scope){ // no equiv
  1983. var start = new Date(), iid;
  1984. var f = function(){
  1985. if(start.getElapsed() > 10000){
  1986. clearInterval(iid);
  1987. }
  1988. var el = document.getElementById(id);
  1989. if(el){
  1990. clearInterval(iid);
  1991. fn.call(scope||window, el);
  1992. }
  1993. };
  1994. iid = setInterval(f, 50);
  1995. }
  1996. };
  1997. Ext.lib.Ajax = function(){
  1998. var createSuccess = function(cb){
  1999. return cb.success ? function(xhr){
  2000. cb.success.call(cb.scope||window, createResponse(cb, xhr));
  2001. } : Ext.emptyFn;
  2002. };
  2003. var createFailure = function(cb){
  2004. return cb.failure ? function(xhr){
  2005. cb.failure.call(cb.scope||window, createResponse(cb, xhr));
  2006. } : Ext.emptyFn;
  2007. };
  2008. var createResponse = function(cb, xhr){
  2009. var headerObj = {},
  2010. headerStr,
  2011. t,
  2012. s;
  2013. try {
  2014. headerStr = xhr.getAllResponseHeaders();
  2015. Ext.each(headerStr.replace(/\r\n/g, '\n').split('\n'), function(v){
  2016. t = v.indexOf(':');
  2017. if(t >= 0){
  2018. s = v.substr(0, t).toLowerCase();
  2019. if(v.charAt(t + 1) == ' '){
  2020. ++t;
  2021. }
  2022. headerObj[s] = v.substr(t + 1);
  2023. }
  2024. });
  2025. } catch(e) {}
  2026. return {
  2027. responseText: xhr.responseText,
  2028. responseXML : xhr.responseXML,
  2029. argument: cb.argument,
  2030. status: xhr.status,
  2031. statusText: xhr.statusText,
  2032. getResponseHeader : function(header){return headerObj[header.toLowerCase()];},
  2033. getAllResponseHeaders : function(){return headerStr}
  2034. };
  2035. };
  2036. return {
  2037. request : function(method, uri, cb, data, options){
  2038. var o = {
  2039. method: method,
  2040. parameters: data || '',
  2041. timeout: cb.timeout,
  2042. onSuccess: createSuccess(cb),
  2043. onFailure: createFailure(cb)
  2044. };
  2045. if(options){
  2046. var hs = options.headers;
  2047. if(hs){
  2048. o.requestHeaders = hs;
  2049. }
  2050. if(options.xmlData){
  2051. method = (method ? method : (options.method ? options.method : 'POST'));
  2052. if (!hs || !hs['Content-Type']){
  2053. o.contentType = 'text/xml';
  2054. }
  2055. o.postBody = options.xmlData;
  2056. delete o.parameters;
  2057. }
  2058. if(options.jsonData){
  2059. method = (method ? method : (options.method ? options.method : 'POST'));
  2060. if (!hs || !hs['Content-Type']){
  2061. o.contentType = 'application/json';
  2062. }
  2063. o.postBody = typeof options.jsonData == 'object' ? Ext.encode(options.jsonData) : options.jsonData;
  2064. delete o.parameters;
  2065. }
  2066. }
  2067. new Ajax.Request(uri, o);
  2068. },
  2069. formRequest : function(form, uri, cb, data, isUpload, sslUri){
  2070. new Ajax.Request(uri, {
  2071. method: Ext.getDom(form).method ||'POST',
  2072. parameters: Form.serialize(form)+(data?'&'+data:''),
  2073. timeout: cb.timeout,
  2074. onSuccess: createSuccess(cb),
  2075. onFailure: createFailure(cb)
  2076. });
  2077. },
  2078. isCallInProgress : function(trans){
  2079. return false;
  2080. },
  2081. abort : function(trans){
  2082. return false;
  2083. },
  2084. serializeForm : function(form){
  2085. return Form.serialize(form.dom||form);
  2086. }
  2087. };
  2088. }();
  2089. Ext.lib.Anim = function(){
  2090. var easings = {
  2091. easeOut: function(pos) {
  2092. return 1-Math.pow(1-pos,2);
  2093. },
  2094. easeIn: function(pos) {
  2095. return 1-Math.pow(1-pos,2);
  2096. }
  2097. };
  2098. var createAnim = function(cb, scope){
  2099. return {
  2100. stop : function(skipToLast){
  2101. this.effect.cancel();
  2102. },
  2103. isAnimated : function(){
  2104. return this.effect.state == 'running';
  2105. },
  2106. proxyCallback : function(){
  2107. Ext.callback(cb, scope);
  2108. }
  2109. };
  2110. };
  2111. return {
  2112. scroll : function(el, args, duration, easing, cb, scope){
  2113. // not supported so scroll immediately?
  2114. var anim = createAnim(cb, scope);
  2115. el = Ext.getDom(el);
  2116. if(typeof args.scroll.to[0] == 'number'){
  2117. el.scrollLeft = args.scroll.to[0];
  2118. }
  2119. if(typeof args.scroll.to[1] == 'number'){
  2120. el.scrollTop = args.scroll.to[1];
  2121. }
  2122. anim.proxyCallback();
  2123. return anim;
  2124. },
  2125. motion : function(el, args, duration, easing, cb, scope){
  2126. return this.run(el, args, duration, easing, cb, scope);
  2127. },
  2128. color : function(el, args, duration, easing, cb, scope){
  2129. return this.run(el, args, duration, easing, cb, scope);
  2130. },
  2131. run : function(el, args, duration, easing, cb, scope, type){
  2132. var o = {};
  2133. for(var k in args){
  2134. switch(k){ // scriptaculous doesn't support, so convert these
  2135. case 'points':
  2136. var by, pts, e = Ext.fly(el, '_animrun');
  2137. e.position();
  2138. if(by = args.points.by){
  2139. var xy = e.getXY();
  2140. pts = e.translatePoints([xy[0]+by[0], xy[1]+by[1]]);
  2141. }else{
  2142. pts = e.translatePoints(args.points.to);
  2143. }
  2144. o.left = pts.left+'px';
  2145. o.top = pts.top+'px';
  2146. break;
  2147. case 'width':
  2148. o.width = args.width.to+'px';
  2149. break;
  2150. case 'height':
  2151. o.height = args.height.to+'px';
  2152. break;
  2153. case 'opacity':
  2154. o.opacity = String(args.opacity.to);
  2155. break;
  2156. default:
  2157. o[k] = String(args[k].to);
  2158. break;
  2159. }
  2160. }
  2161. var anim = createAnim(cb, scope);
  2162. anim.effect = new Effect.Morph(Ext.id(el), {
  2163. duration: duration,
  2164. afterFinish: anim.proxyCallback,
  2165. transition: easings[easing] || Effect.Transitions.linear,
  2166. style: o
  2167. });
  2168. return anim;
  2169. }
  2170. };
  2171. }();
  2172. // all lib flyweight calls use their own flyweight to prevent collisions with developer flyweights
  2173. function fly(el){
  2174. if(!libFlyweight){
  2175. libFlyweight = new Ext.Element.Flyweight();
  2176. }
  2177. libFlyweight.dom = el;
  2178. return libFlyweight;
  2179. }
  2180. Ext.lib.Region = function(t, r, b, l) {
  2181. this.top = t;
  2182. this[1] = t;
  2183. this.right = r;
  2184. this.bottom = b;
  2185. this.left = l;
  2186. this[0] = l;
  2187. };
  2188. Ext.lib.Region.prototype = {
  2189. contains : function(region) {
  2190. return ( region.left >= this.left &&
  2191. region.right <= this.right &&
  2192. region.top >= this.top &&
  2193. region.bottom <= this.bottom );
  2194. },
  2195. getArea : function() {
  2196. return ( (this.bottom - this.top) * (this.right - this.left) );
  2197. },
  2198. intersect : function(region) {
  2199. var t = Math.max( this.top, region.top );
  2200. var r = Math.min( this.right, region.right );
  2201. var b = Math.min( this.bottom, region.bottom );
  2202. var l = Math.max( this.left, region.left );
  2203. if (b >= t && r >= l) {
  2204. return new Ext.lib.Region(t, r, b, l);
  2205. } else {
  2206. return null;
  2207. }
  2208. },
  2209. union : function(region) {
  2210. var t = Math.min( this.top, region.top );
  2211. var r = Math.max( this.right, region.right );
  2212. var b = Math.max( this.bottom, region.bottom );
  2213. var l = Math.min( this.left, region.left );
  2214. return new Ext.lib.Region(t, r, b, l);
  2215. },
  2216. constrainTo : function(r) {
  2217. this.top = this.top.constrain(r.top, r.bottom);
  2218. this.bottom = this.bottom.constrain(r.top, r.bottom);
  2219. this.left = this.left.constrain(r.left, r.right);
  2220. this.right = this.right.constrain(r.left, r.right);
  2221. return this;
  2222. },
  2223. adjust : function(t, l, b, r){
  2224. this.top += t;
  2225. this.left += l;
  2226. this.right += r;
  2227. this.bottom += b;
  2228. return this;
  2229. }
  2230. };
  2231. Ext.lib.Region.getRegion = function(el) {
  2232. var p = Ext.lib.Dom.getXY(el);
  2233. var t = p[1];
  2234. var r = p[0] + el.offsetWidth;
  2235. var b = p[1] + el.offsetHeight;
  2236. var l = p[0];
  2237. return new Ext.lib.Region(t, r, b, l);
  2238. };
  2239. Ext.lib.Point = function(x, y) {
  2240. if (Ext.isArray(x)) {
  2241. y = x[1];
  2242. x = x[0];
  2243. }
  2244. this.x = this.right = this.left = this[0] = x;
  2245. this.y = this.top = this.bottom = this[1] = y;
  2246. };
  2247. Ext.lib.Point.prototype = new Ext.lib.Region();
  2248. // prevent IE leaks
  2249. if(Ext.isIE) {
  2250. function fnCleanUp() {
  2251. var p = Function.prototype;
  2252. delete p.createSequence;
  2253. delete p.defer;
  2254. delete p.createDelegate;
  2255. delete p.createCallback;
  2256. delete p.createInterceptor;
  2257. window.detachEvent("onunload", fnCleanUp);
  2258. }
  2259. window.attachEvent("onunload", fnCleanUp);
  2260. }
  2261. })();