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.

2009 lines
74 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. /**
  8. * @class Ext.Window
  9. * @extends Ext.Panel
  10. * <p>A specialized panel intended for use as an application window. Windows are floated, {@link #resizable}, and
  11. * {@link #draggable} by default. Windows can be {@link #maximizable maximized} to fill the viewport,
  12. * restored to their prior size, and can be {@link #minimize}d.</p>
  13. * <p>Windows can also be linked to a {@link Ext.WindowGroup} or managed by the {@link Ext.WindowMgr} to provide
  14. * grouping, activation, to front, to back and other application-specific behavior.</p>
  15. * <p>By default, Windows will be rendered to document.body. To {@link #constrain} a Window to another element
  16. * specify {@link Ext.Component#renderTo renderTo}.</p>
  17. * <p><b>Note:</b> By default, the <code>{@link #closable close}</code> header tool <i>destroys</i> the Window resulting in
  18. * destruction of any child Components. This makes the Window object, and all its descendants <b>unusable</b>. To enable
  19. * re-use of a Window, use <b><code>{@link #closeAction closeAction: 'hide'}</code></b>.</p>
  20. * @constructor
  21. * @param {Object} config The config object
  22. * @xtype window
  23. */
  24. Ext.Window = Ext.extend(Ext.Panel, {
  25. /**
  26. * @cfg {Number} x
  27. * The X position of the left edge of the window on initial showing. Defaults to centering the Window within
  28. * the width of the Window's container {@link Ext.Element Element) (The Element that the Window is rendered to).
  29. */
  30. /**
  31. * @cfg {Number} y
  32. * The Y position of the top edge of the window on initial showing. Defaults to centering the Window within
  33. * the height of the Window's container {@link Ext.Element Element) (The Element that the Window is rendered to).
  34. */
  35. /**
  36. * @cfg {Boolean} modal
  37. * True to make the window modal and mask everything behind it when displayed, false to display it without
  38. * restricting access to other UI elements (defaults to false).
  39. */
  40. /**
  41. * @cfg {String/Element} animateTarget
  42. * Id or element from which the window should animate while opening (defaults to null with no animation).
  43. */
  44. /**
  45. * @cfg {String} resizeHandles
  46. * A valid {@link Ext.Resizable} handles config string (defaults to 'all'). Only applies when resizable = true.
  47. */
  48. /**
  49. * @cfg {Ext.WindowGroup} manager
  50. * A reference to the WindowGroup that should manage this window (defaults to {@link Ext.WindowMgr}).
  51. */
  52. /**
  53. * @cfg {String/Number/Component} defaultButton
  54. * <p>Specifies a Component to receive focus when this Window is focussed.</p>
  55. * <p>This may be one of:</p><div class="mdetail-params"><ul>
  56. * <li>The index of a footer Button.</li>
  57. * <li>The id of a Component.</li>
  58. * <li>A Component.</li>
  59. * </ul></div>
  60. */
  61. /**
  62. * @cfg {Function} onEsc
  63. * Allows override of the built-in processing for the escape key. Default action
  64. * is to close the Window (performing whatever action is specified in {@link #closeAction}.
  65. * To prevent the Window closing when the escape key is pressed, specify this as
  66. * Ext.emptyFn (See {@link Ext#emptyFn}).
  67. */
  68. /**
  69. * @cfg {Boolean} collapsed
  70. * True to render the window collapsed, false to render it expanded (defaults to false). Note that if
  71. * {@link #expandOnShow} is true (the default) it will override the <tt>collapsed</tt> config and the window
  72. * will always be expanded when shown.
  73. */
  74. /**
  75. * @cfg {Boolean} maximized
  76. * True to initially display the window in a maximized state. (Defaults to false).
  77. */
  78. /**
  79. * @cfg {String} baseCls
  80. * The base CSS class to apply to this panel's element (defaults to 'x-window').
  81. */
  82. baseCls : 'x-window',
  83. /**
  84. * @cfg {Boolean} resizable
  85. * True to allow user resizing at each edge and corner of the window, false to disable resizing (defaults to true).
  86. */
  87. resizable : true,
  88. /**
  89. * @cfg {Boolean} draggable
  90. * True to allow the window to be dragged by the header bar, false to disable dragging (defaults to true). Note
  91. * that by default the window will be centered in the viewport, so if dragging is disabled the window may need
  92. * to be positioned programmatically after render (e.g., myWindow.setPosition(100, 100);).
  93. */
  94. draggable : true,
  95. /**
  96. * @cfg {Boolean} closable
  97. * <p>True to display the 'close' tool button and allow the user to close the window, false to
  98. * hide the button and disallow closing the window (defaults to true).</p>
  99. * <p>By default, when close is requested by either clicking the close button in the header
  100. * or pressing ESC when the Window has focus, the {@link #close} method will be called. This
  101. * will <i>{@link Ext.Component#destroy destroy}</i> the Window and its content meaning that
  102. * it may not be reused.</p>
  103. * <p>To make closing a Window <i>hide</i> the Window so that it may be reused, set
  104. * {@link #closeAction} to 'hide'.
  105. */
  106. closable : true,
  107. /**
  108. * @cfg {String} closeAction
  109. * <p>The action to take when the close header tool is clicked:
  110. * <div class="mdetail-params"><ul>
  111. * <li><b><code>'{@link #close}'</code></b> : <b>Default</b><div class="sub-desc">
  112. * {@link #close remove} the window from the DOM and {@link Ext.Component#destroy destroy}
  113. * it and all descendant Components. The window will <b>not</b> be available to be
  114. * redisplayed via the {@link #show} method.
  115. * </div></li>
  116. * <li><b><code>'{@link #hide}'</code></b> : <div class="sub-desc">
  117. * {@link #hide} the window by setting visibility to hidden and applying negative offsets.
  118. * The window will be available to be redisplayed via the {@link #show} method.
  119. * </div></li>
  120. * </ul></div>
  121. * <p><b>Note:</b> This setting does not affect the {@link #close} method
  122. * which will always {@link Ext.Component#destroy destroy} the window. To
  123. * programatically <i>hide</i> a window, call {@link #hide}.</p>
  124. */
  125. closeAction : 'close',
  126. /**
  127. * @cfg {Boolean} constrain
  128. * True to constrain the window within its containing element, false to allow it to fall outside of its
  129. * containing element. By default the window will be rendered to document.body. To render and constrain the
  130. * window within another element specify {@link #renderTo}.
  131. * (defaults to false). Optionally the header only can be constrained using {@link #constrainHeader}.
  132. */
  133. constrain : false,
  134. /**
  135. * @cfg {Boolean} constrainHeader
  136. * True to constrain the window header within its containing element (allowing the window body to fall outside
  137. * of its containing element) or false to allow the header to fall outside its containing element (defaults to
  138. * false). Optionally the entire window can be constrained using {@link #constrain}.
  139. */
  140. constrainHeader : false,
  141. /**
  142. * @cfg {Boolean} plain
  143. * True to render the window body with a transparent background so that it will blend into the framing
  144. * elements, false to add a lighter background color to visually highlight the body element and separate it
  145. * more distinctly from the surrounding frame (defaults to false).
  146. */
  147. plain : false,
  148. /**
  149. * @cfg {Boolean} minimizable
  150. * True to display the 'minimize' tool button and allow the user to minimize the window, false to hide the button
  151. * and disallow minimizing the window (defaults to false). Note that this button provides no implementation --
  152. * the behavior of minimizing a window is implementation-specific, so the minimize event must be handled and a
  153. * custom minimize behavior implemented for this option to be useful.
  154. */
  155. minimizable : false,
  156. /**
  157. * @cfg {Boolean} maximizable
  158. * True to display the 'maximize' tool button and allow the user to maximize the window, false to hide the button
  159. * and disallow maximizing the window (defaults to false). Note that when a window is maximized, the tool button
  160. * will automatically change to a 'restore' button with the appropriate behavior already built-in that will
  161. * restore the window to its previous size.
  162. */
  163. maximizable : false,
  164. /**
  165. * @cfg {Number} minHeight
  166. * The minimum height in pixels allowed for this window (defaults to 100). Only applies when resizable = true.
  167. */
  168. minHeight : 100,
  169. /**
  170. * @cfg {Number} minWidth
  171. * The minimum width in pixels allowed for this window (defaults to 200). Only applies when resizable = true.
  172. */
  173. minWidth : 200,
  174. /**
  175. * @cfg {Boolean} expandOnShow
  176. * True to always expand the window when it is displayed, false to keep it in its current state (which may be
  177. * {@link #collapsed}) when displayed (defaults to true).
  178. */
  179. expandOnShow : true,
  180. // inherited docs, same default
  181. collapsible : false,
  182. /**
  183. * @cfg {Boolean} initHidden
  184. * True to hide the window until show() is explicitly called (defaults to true).
  185. * @deprecated
  186. */
  187. initHidden : undefined,
  188. /**
  189. * @cfg {Boolean} hidden
  190. * Render this component hidden (default is <tt>true</tt>). If <tt>true</tt>, the
  191. * {@link #hide} method will be called internally.
  192. */
  193. hidden : true,
  194. // The following configs are set to provide the basic functionality of a window.
  195. // Changing them would require additional code to handle correctly and should
  196. // usually only be done in subclasses that can provide custom behavior. Changing them
  197. // may have unexpected or undesirable results.
  198. /** @cfg {String} elements @hide */
  199. elements : 'header,body',
  200. /** @cfg {Boolean} frame @hide */
  201. frame : true,
  202. /** @cfg {Boolean} floating @hide */
  203. floating : true,
  204. // private
  205. initComponent : function(){
  206. this.initTools();
  207. Ext.Window.superclass.initComponent.call(this);
  208. this.addEvents(
  209. /**
  210. * @event activate
  211. * Fires after the window has been visually activated via {@link #setActive}.
  212. * @param {Ext.Window} this
  213. */
  214. /**
  215. * @event deactivate
  216. * Fires after the window has been visually deactivated via {@link #setActive}.
  217. * @param {Ext.Window} this
  218. */
  219. /**
  220. * @event resize
  221. * Fires after the window has been resized.
  222. * @param {Ext.Window} this
  223. * @param {Number} width The window's new width
  224. * @param {Number} height The window's new height
  225. */
  226. 'resize',
  227. /**
  228. * @event maximize
  229. * Fires after the window has been maximized.
  230. * @param {Ext.Window} this
  231. */
  232. 'maximize',
  233. /**
  234. * @event minimize
  235. * Fires after the window has been minimized.
  236. * @param {Ext.Window} this
  237. */
  238. 'minimize',
  239. /**
  240. * @event restore
  241. * Fires after the window has been restored to its original size after being maximized.
  242. * @param {Ext.Window} this
  243. */
  244. 'restore'
  245. );
  246. // for backwards compat, this should be removed at some point
  247. if(Ext.isDefined(this.initHidden)){
  248. this.hidden = this.initHidden;
  249. }
  250. if(this.hidden === false){
  251. this.hidden = true;
  252. this.show();
  253. }
  254. },
  255. // private
  256. getState : function(){
  257. return Ext.apply(Ext.Window.superclass.getState.call(this) || {}, this.getBox(true));
  258. },
  259. // private
  260. onRender : function(ct, position){
  261. Ext.Window.superclass.onRender.call(this, ct, position);
  262. if(this.plain){
  263. this.el.addClass('x-window-plain');
  264. }
  265. // this element allows the Window to be focused for keyboard events
  266. this.focusEl = this.el.createChild({
  267. tag: 'a', href:'#', cls:'x-dlg-focus',
  268. tabIndex:'-1', html: '&#160;'});
  269. this.focusEl.swallowEvent('click', true);
  270. this.proxy = this.el.createProxy('x-window-proxy');
  271. this.proxy.enableDisplayMode('block');
  272. if(this.modal){
  273. this.mask = this.container.createChild({cls:'ext-el-mask'}, this.el.dom);
  274. this.mask.enableDisplayMode('block');
  275. this.mask.hide();
  276. this.mon(this.mask, 'click', this.focus, this);
  277. }
  278. if(this.maximizable){
  279. this.mon(this.header, 'dblclick', this.toggleMaximize, this);
  280. }
  281. },
  282. // private
  283. initEvents : function(){
  284. Ext.Window.superclass.initEvents.call(this);
  285. if(this.animateTarget){
  286. this.setAnimateTarget(this.animateTarget);
  287. }
  288. if(this.resizable){
  289. this.resizer = new Ext.Resizable(this.el, {
  290. minWidth: this.minWidth,
  291. minHeight:this.minHeight,
  292. handles: this.resizeHandles || 'all',
  293. pinned: true,
  294. resizeElement : this.resizerAction,
  295. handleCls: 'x-window-handle'
  296. });
  297. this.resizer.window = this;
  298. this.mon(this.resizer, 'beforeresize', this.beforeResize, this);
  299. }
  300. if(this.draggable){
  301. this.header.addClass('x-window-draggable');
  302. }
  303. this.mon(this.el, 'mousedown', this.toFront, this);
  304. this.manager = this.manager || Ext.WindowMgr;
  305. this.manager.register(this);
  306. if(this.maximized){
  307. this.maximized = false;
  308. this.maximize();
  309. }
  310. if(this.closable){
  311. var km = this.getKeyMap();
  312. km.on(27, this.onEsc, this);
  313. km.disable();
  314. }
  315. },
  316. initDraggable : function(){
  317. /**
  318. * <p>If this Window is configured {@link #draggable}, this property will contain
  319. * an instance of {@link Ext.dd.DD} which handles dragging the Window's DOM Element.</p>
  320. * <p>This has implementations of <code>startDrag</code>, <code>onDrag</code> and <code>endDrag</code>
  321. * which perform the dragging action. If extra logic is needed at these points, use
  322. * {@link Function#createInterceptor createInterceptor} or {@link Function#createSequence createSequence} to
  323. * augment the existing implementations.</p>
  324. * @type Ext.dd.DD
  325. * @property dd
  326. */
  327. this.dd = new Ext.Window.DD(this);
  328. },
  329. // private
  330. onEsc : function(k, e){
  331. e.stopEvent();
  332. this[this.closeAction]();
  333. },
  334. // private
  335. beforeDestroy : function(){
  336. if(this.rendered){
  337. this.hide();
  338. this.clearAnchor();
  339. Ext.destroy(
  340. this.focusEl,
  341. this.resizer,
  342. this.dd,
  343. this.proxy,
  344. this.mask
  345. );
  346. }
  347. Ext.Window.superclass.beforeDestroy.call(this);
  348. },
  349. // private
  350. onDestroy : function(){
  351. if(this.manager){
  352. this.manager.unregister(this);
  353. }
  354. Ext.Window.superclass.onDestroy.call(this);
  355. },
  356. // private
  357. initTools : function(){
  358. if(this.minimizable){
  359. this.addTool({
  360. id: 'minimize',
  361. handler: this.minimize.createDelegate(this, [])
  362. });
  363. }
  364. if(this.maximizable){
  365. this.addTool({
  366. id: 'maximize',
  367. handler: this.maximize.createDelegate(this, [])
  368. });
  369. this.addTool({
  370. id: 'restore',
  371. handler: this.restore.createDelegate(this, []),
  372. hidden:true
  373. });
  374. }
  375. if(this.closable){
  376. this.addTool({
  377. id: 'close',
  378. handler: this[this.closeAction].createDelegate(this, [])
  379. });
  380. }
  381. },
  382. // private
  383. resizerAction : function(){
  384. var box = this.proxy.getBox();
  385. this.proxy.hide();
  386. this.window.handleResize(box);
  387. return box;
  388. },
  389. // private
  390. beforeResize : function(){
  391. this.resizer.minHeight = Math.max(this.minHeight, this.getFrameHeight() + 40); // 40 is a magic minimum content size?
  392. this.resizer.minWidth = Math.max(this.minWidth, this.getFrameWidth() + 40);
  393. this.resizeBox = this.el.getBox();
  394. },
  395. // private
  396. updateHandles : function(){
  397. if(Ext.isIE && this.resizer){
  398. this.resizer.syncHandleHeight();
  399. this.el.repaint();
  400. }
  401. },
  402. // private
  403. handleResize : function(box){
  404. var rz = this.resizeBox;
  405. if(rz.x != box.x || rz.y != box.y){
  406. this.updateBox(box);
  407. }else{
  408. this.setSize(box);
  409. if (Ext.isIE6 && Ext.isStrict) {
  410. this.doLayout();
  411. }
  412. }
  413. this.focus();
  414. this.updateHandles();
  415. this.saveState();
  416. },
  417. /**
  418. * Focuses the window. If a defaultButton is set, it will receive focus, otherwise the
  419. * window itself will receive focus.
  420. */
  421. focus : function(){
  422. var f = this.focusEl,
  423. db = this.defaultButton,
  424. t = typeof db,
  425. el,
  426. ct;
  427. if(Ext.isDefined(db)){
  428. if(Ext.isNumber(db) && this.fbar){
  429. f = this.fbar.items.get(db);
  430. }else if(Ext.isString(db)){
  431. f = Ext.getCmp(db);
  432. }else{
  433. f = db;
  434. }
  435. el = f.getEl();
  436. ct = Ext.getDom(this.container);
  437. if (el && ct) {
  438. if (!Ext.lib.Region.getRegion(ct).contains(Ext.lib.Region.getRegion(el.dom))){
  439. return;
  440. }
  441. }
  442. }
  443. f = f || this.focusEl;
  444. f.focus.defer(10, f);
  445. },
  446. /**
  447. * Sets the target element from which the window should animate while opening.
  448. * @param {String/Element} el The target element or id
  449. */
  450. setAnimateTarget : function(el){
  451. el = Ext.get(el);
  452. this.animateTarget = el;
  453. },
  454. // private
  455. beforeShow : function(){
  456. delete this.el.lastXY;
  457. delete this.el.lastLT;
  458. if(this.x === undefined || this.y === undefined){
  459. var xy = this.el.getAlignToXY(this.container, 'c-c');
  460. var pos = this.el.translatePoints(xy[0], xy[1]);
  461. this.x = this.x === undefined? pos.left : this.x;
  462. this.y = this.y === undefined? pos.top : this.y;
  463. }
  464. this.el.setLeftTop(this.x, this.y);
  465. if(this.expandOnShow){
  466. this.expand(false);
  467. }
  468. if(this.modal){
  469. Ext.getBody().addClass('x-body-masked');
  470. this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
  471. this.mask.show();
  472. }
  473. },
  474. /**
  475. * Shows the window, rendering it first if necessary, or activates it and brings it to front if hidden.
  476. * @param {String/Element} animateTarget (optional) The target element or id from which the window should
  477. * animate while opening (defaults to null with no animation)
  478. * @param {Function} callback (optional) A callback function to call after the window is displayed
  479. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Window.
  480. * @return {Ext.Window} this
  481. */
  482. show : function(animateTarget, cb, scope){
  483. if(!this.rendered){
  484. this.render(Ext.getBody());
  485. }
  486. if(this.hidden === false){
  487. this.toFront();
  488. return this;
  489. }
  490. if(this.fireEvent('beforeshow', this) === false){
  491. return this;
  492. }
  493. if(cb){
  494. this.on('show', cb, scope, {single:true});
  495. }
  496. this.hidden = false;
  497. if(Ext.isDefined(animateTarget)){
  498. this.setAnimateTarget(animateTarget);
  499. }
  500. this.beforeShow();
  501. if(this.animateTarget){
  502. this.animShow();
  503. }else{
  504. this.afterShow();
  505. }
  506. return this;
  507. },
  508. // private
  509. afterShow : function(isAnim){
  510. if (this.isDestroyed){
  511. return false;
  512. }
  513. this.proxy.hide();
  514. this.el.setStyle('display', 'block');
  515. this.el.show();
  516. if(this.maximized){
  517. this.fitContainer();
  518. }
  519. if(Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
  520. this.cascade(this.setAutoScroll);
  521. }
  522. if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
  523. Ext.EventManager.onWindowResize(this.onWindowResize, this);
  524. }
  525. this.doConstrain();
  526. this.doLayout();
  527. if(this.keyMap){
  528. this.keyMap.enable();
  529. }
  530. this.toFront();
  531. this.updateHandles();
  532. if(isAnim && (Ext.isIE || Ext.isWebKit)){
  533. var sz = this.getSize();
  534. this.onResize(sz.width, sz.height);
  535. }
  536. this.onShow();
  537. this.fireEvent('show', this);
  538. },
  539. // private
  540. animShow : function(){
  541. this.proxy.show();
  542. this.proxy.setBox(this.animateTarget.getBox());
  543. this.proxy.setOpacity(0);
  544. var b = this.getBox();
  545. this.el.setStyle('display', 'none');
  546. this.proxy.shift(Ext.apply(b, {
  547. callback: this.afterShow.createDelegate(this, [true], false),
  548. scope: this,
  549. easing: 'easeNone',
  550. duration: 0.25,
  551. opacity: 0.5
  552. }));
  553. },
  554. /**
  555. * Hides the window, setting it to invisible and applying negative offsets.
  556. * @param {String/Element} animateTarget (optional) The target element or id to which the window should
  557. * animate while hiding (defaults to null with no animation)
  558. * @param {Function} callback (optional) A callback function to call after the window is hidden
  559. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to this Window.
  560. * @return {Ext.Window} this
  561. */
  562. hide : function(animateTarget, cb, scope){
  563. if(this.hidden || this.fireEvent('beforehide', this) === false){
  564. return this;
  565. }
  566. if(cb){
  567. this.on('hide', cb, scope, {single:true});
  568. }
  569. this.hidden = true;
  570. if(animateTarget !== undefined){
  571. this.setAnimateTarget(animateTarget);
  572. }
  573. if(this.modal){
  574. this.mask.hide();
  575. Ext.getBody().removeClass('x-body-masked');
  576. }
  577. if(this.animateTarget){
  578. this.animHide();
  579. }else{
  580. this.el.hide();
  581. this.afterHide();
  582. }
  583. return this;
  584. },
  585. // private
  586. afterHide : function(){
  587. this.proxy.hide();
  588. if(this.monitorResize || this.modal || this.constrain || this.constrainHeader){
  589. Ext.EventManager.removeResizeListener(this.onWindowResize, this);
  590. }
  591. if(this.keyMap){
  592. this.keyMap.disable();
  593. }
  594. this.onHide();
  595. this.fireEvent('hide', this);
  596. },
  597. // private
  598. animHide : function(){
  599. this.proxy.setOpacity(0.5);
  600. this.proxy.show();
  601. var tb = this.getBox(false);
  602. this.proxy.setBox(tb);
  603. this.el.hide();
  604. this.proxy.shift(Ext.apply(this.animateTarget.getBox(), {
  605. callback: this.afterHide,
  606. scope: this,
  607. duration: 0.25,
  608. easing: 'easeNone',
  609. opacity: 0
  610. }));
  611. },
  612. /**
  613. * Method that is called immediately before the <code>show</code> event is fired.
  614. * Defaults to <code>Ext.emptyFn</code>.
  615. */
  616. onShow : Ext.emptyFn,
  617. /**
  618. * Method that is called immediately before the <code>hide</code> event is fired.
  619. * Defaults to <code>Ext.emptyFn</code>.
  620. */
  621. onHide : Ext.emptyFn,
  622. // private
  623. onWindowResize : function(){
  624. if(this.maximized){
  625. this.fitContainer();
  626. }
  627. if(this.modal){
  628. this.mask.setSize('100%', '100%');
  629. var force = this.mask.dom.offsetHeight;
  630. this.mask.setSize(Ext.lib.Dom.getViewWidth(true), Ext.lib.Dom.getViewHeight(true));
  631. }
  632. this.doConstrain();
  633. },
  634. // private
  635. doConstrain : function(){
  636. if(this.constrain || this.constrainHeader){
  637. var offsets;
  638. if(this.constrain){
  639. offsets = {
  640. right:this.el.shadowOffset,
  641. left:this.el.shadowOffset,
  642. bottom:this.el.shadowOffset
  643. };
  644. }else {
  645. var s = this.getSize();
  646. offsets = {
  647. right:-(s.width - 100),
  648. bottom:-(s.height - 25)
  649. };
  650. }
  651. var xy = this.el.getConstrainToXY(this.container, true, offsets);
  652. if(xy){
  653. this.setPosition(xy[0], xy[1]);
  654. }
  655. }
  656. },
  657. // private - used for dragging
  658. ghost : function(cls){
  659. var ghost = this.createGhost(cls);
  660. var box = this.getBox(true);
  661. ghost.setLeftTop(box.x, box.y);
  662. ghost.setWidth(box.width);
  663. this.el.hide();
  664. this.activeGhost = ghost;
  665. return ghost;
  666. },
  667. // private
  668. unghost : function(show, matchPosition){
  669. if(!this.activeGhost) {
  670. return;
  671. }
  672. if(show !== false){
  673. this.el.show();
  674. this.focus.defer(10, this);
  675. if(Ext.isMac && Ext.isGecko2){ // work around stupid FF 2.0/Mac scroll bar bug
  676. this.cascade(this.setAutoScroll);
  677. }
  678. }
  679. if(matchPosition !== false){
  680. this.setPosition(this.activeGhost.getLeft(true), this.activeGhost.getTop(true));
  681. }
  682. this.activeGhost.hide();
  683. this.activeGhost.remove();
  684. delete this.activeGhost;
  685. },
  686. /**
  687. * Placeholder method for minimizing the window. By default, this method simply fires the {@link #minimize} event
  688. * since the behavior of minimizing a window is application-specific. To implement custom minimize behavior,
  689. * either the minimize event can be handled or this method can be overridden.
  690. * @return {Ext.Window} this
  691. */
  692. minimize : function(){
  693. this.fireEvent('minimize', this);
  694. return this;
  695. },
  696. /**
  697. * <p>Closes the Window, removes it from the DOM, {@link Ext.Component#destroy destroy}s
  698. * the Window object and all its descendant Components. The {@link Ext.Panel#beforeclose beforeclose}
  699. * event is fired before the close happens and will cancel the close action if it returns false.<p>
  700. * <p><b>Note:</b> This method is not affected by the {@link #closeAction} setting which
  701. * only affects the action triggered when clicking the {@link #closable 'close' tool in the header}.
  702. * To hide the Window without destroying it, call {@link #hide}.</p>
  703. */
  704. close : function(){
  705. if(this.fireEvent('beforeclose', this) !== false){
  706. if(this.hidden){
  707. this.doClose();
  708. }else{
  709. this.hide(null, this.doClose, this);
  710. }
  711. }
  712. },
  713. // private
  714. doClose : function(){
  715. this.fireEvent('close', this);
  716. this.destroy();
  717. },
  718. /**
  719. * Fits the window within its current container and automatically replaces
  720. * the {@link #maximizable 'maximize' tool button} with the 'restore' tool button.
  721. * Also see {@link #toggleMaximize}.
  722. * @return {Ext.Window} this
  723. */
  724. maximize : function(){
  725. if(!this.maximized){
  726. this.expand(false);
  727. this.restoreSize = this.getSize();
  728. this.restorePos = this.getPosition(true);
  729. if (this.maximizable){
  730. this.tools.maximize.hide();
  731. this.tools.restore.show();
  732. }
  733. this.maximized = true;
  734. this.el.disableShadow();
  735. if(this.dd){
  736. this.dd.lock();
  737. }
  738. if(this.collapsible){
  739. this.tools.toggle.hide();
  740. }
  741. this.el.addClass('x-window-maximized');
  742. this.container.addClass('x-window-maximized-ct');
  743. this.setPosition(0, 0);
  744. this.fitContainer();
  745. this.fireEvent('maximize', this);
  746. }
  747. return this;
  748. },
  749. /**
  750. * Restores a {@link #maximizable maximized} window back to its original
  751. * size and position prior to being maximized and also replaces
  752. * the 'restore' tool button with the 'maximize' tool button.
  753. * Also see {@link #toggleMaximize}.
  754. * @return {Ext.Window} this
  755. */
  756. restore : function(){
  757. if(this.maximized){
  758. var t = this.tools;
  759. this.el.removeClass('x-window-maximized');
  760. if(t.restore){
  761. t.restore.hide();
  762. }
  763. if(t.maximize){
  764. t.maximize.show();
  765. }
  766. this.setPosition(this.restorePos[0], this.restorePos[1]);
  767. this.setSize(this.restoreSize.width, this.restoreSize.height);
  768. delete this.restorePos;
  769. delete this.restoreSize;
  770. this.maximized = false;
  771. this.el.enableShadow(true);
  772. if(this.dd){
  773. this.dd.unlock();
  774. }
  775. if(this.collapsible && t.toggle){
  776. t.toggle.show();
  777. }
  778. this.container.removeClass('x-window-maximized-ct');
  779. this.doConstrain();
  780. this.fireEvent('restore', this);
  781. }
  782. return this;
  783. },
  784. /**
  785. * A shortcut method for toggling between {@link #maximize} and {@link #restore} based on the current maximized
  786. * state of the window.
  787. * @return {Ext.Window} this
  788. */
  789. toggleMaximize : function(){
  790. return this[this.maximized ? 'restore' : 'maximize']();
  791. },
  792. // private
  793. fitContainer : function(){
  794. var vs = this.container.getViewSize(false);
  795. this.setSize(vs.width, vs.height);
  796. },
  797. // private
  798. // z-index is managed by the WindowManager and may be overwritten at any time
  799. setZIndex : function(index){
  800. if(this.modal){
  801. this.mask.setStyle('z-index', index);
  802. }
  803. this.el.setZIndex(++index);
  804. index += 5;
  805. if(this.resizer){
  806. this.resizer.proxy.setStyle('z-index', ++index);
  807. }
  808. this.lastZIndex = index;
  809. },
  810. /**
  811. * Aligns the window to the specified element
  812. * @param {Mixed} element The element to align to.
  813. * @param {String} position (optional, defaults to "tl-bl?") The position to align to (see {@link Ext.Element#alignTo} for more details).
  814. * @param {Array} offsets (optional) Offset the positioning by [x, y]
  815. * @return {Ext.Window} this
  816. */
  817. alignTo : function(element, position, offsets){
  818. var xy = this.el.getAlignToXY(element, position, offsets);
  819. this.setPagePosition(xy[0], xy[1]);
  820. return this;
  821. },
  822. /**
  823. * Anchors this window to another element and realigns it when the window is resized or scrolled.
  824. * @param {Mixed} element The element to align to.
  825. * @param {String} position The position to align to (see {@link Ext.Element#alignTo} for more details)
  826. * @param {Array} offsets (optional) Offset the positioning by [x, y]
  827. * @param {Boolean/Number} monitorScroll (optional) true to monitor body scroll and reposition. If this parameter
  828. * is a number, it is used as the buffer delay (defaults to 50ms).
  829. * @return {Ext.Window} this
  830. */
  831. anchorTo : function(el, alignment, offsets, monitorScroll){
  832. this.clearAnchor();
  833. this.anchorTarget = {
  834. el: el,
  835. alignment: alignment,
  836. offsets: offsets
  837. };
  838. Ext.EventManager.onWindowResize(this.doAnchor, this);
  839. var tm = typeof monitorScroll;
  840. if(tm != 'undefined'){
  841. Ext.EventManager.on(window, 'scroll', this.doAnchor, this,
  842. {buffer: tm == 'number' ? monitorScroll : 50});
  843. }
  844. return this.doAnchor();
  845. },
  846. /**
  847. * Performs the anchor, using the saved anchorTarget property.
  848. * @return {Ext.Window} this
  849. * @private
  850. */
  851. doAnchor : function(){
  852. var o = this.anchorTarget;
  853. this.alignTo(o.el, o.alignment, o.offsets);
  854. return this;
  855. },
  856. /**
  857. * Removes any existing anchor from this window. See {@link #anchorTo}.
  858. * @return {Ext.Window} this
  859. */
  860. clearAnchor : function(){
  861. if(this.anchorTarget){
  862. Ext.EventManager.removeResizeListener(this.doAnchor, this);
  863. Ext.EventManager.un(window, 'scroll', this.doAnchor, this);
  864. delete this.anchorTarget;
  865. }
  866. return this;
  867. },
  868. /**
  869. * Brings this window to the front of any other visible windows
  870. * @param {Boolean} e (optional) Specify <tt>false</tt> to prevent the window from being focused.
  871. * @return {Ext.Window} this
  872. */
  873. toFront : function(e){
  874. if(this.manager.bringToFront(this)){
  875. if(!e || !e.getTarget().focus){
  876. this.focus();
  877. }
  878. }
  879. return this;
  880. },
  881. /**
  882. * Makes this the active window by showing its shadow, or deactivates it by hiding its shadow. This method also
  883. * fires the {@link #activate} or {@link #deactivate} event depending on which action occurred. This method is
  884. * called internally by {@link Ext.WindowMgr}.
  885. * @param {Boolean} active True to activate the window, false to deactivate it (defaults to false)
  886. */
  887. setActive : function(active){
  888. if(active){
  889. if(!this.maximized){
  890. this.el.enableShadow(true);
  891. }
  892. this.fireEvent('activate', this);
  893. }else{
  894. this.el.disableShadow();
  895. this.fireEvent('deactivate', this);
  896. }
  897. },
  898. /**
  899. * Sends this window to the back of (lower z-index than) any other visible windows
  900. * @return {Ext.Window} this
  901. */
  902. toBack : function(){
  903. this.manager.sendToBack(this);
  904. return this;
  905. },
  906. /**
  907. * Centers this window in the viewport
  908. * @return {Ext.Window} this
  909. */
  910. center : function(){
  911. var xy = this.el.getAlignToXY(this.container, 'c-c');
  912. this.setPagePosition(xy[0], xy[1]);
  913. return this;
  914. }
  915. /**
  916. * @cfg {Boolean} autoWidth @hide
  917. **/
  918. });
  919. Ext.reg('window', Ext.Window);
  920. // private - custom Window DD implementation
  921. Ext.Window.DD = function(win){
  922. this.win = win;
  923. Ext.Window.DD.superclass.constructor.call(this, win.el.id, 'WindowDD-'+win.id);
  924. this.setHandleElId(win.header.id);
  925. this.scroll = false;
  926. };
  927. Ext.extend(Ext.Window.DD, Ext.dd.DD, {
  928. moveOnly:true,
  929. headerOffsets:[100, 25],
  930. startDrag : function(){
  931. var w = this.win;
  932. this.proxy = w.ghost();
  933. if(w.constrain !== false){
  934. var so = w.el.shadowOffset;
  935. this.constrainTo(w.container, {right: so, left: so, bottom: so});
  936. }else if(w.constrainHeader !== false){
  937. var s = this.proxy.getSize();
  938. this.constrainTo(w.container, {right: -(s.width-this.headerOffsets[0]), bottom: -(s.height-this.headerOffsets[1])});
  939. }
  940. },
  941. b4Drag : Ext.emptyFn,
  942. onDrag : function(e){
  943. this.alignElWithMouse(this.proxy, e.getPageX(), e.getPageY());
  944. },
  945. endDrag : function(e){
  946. this.win.unghost();
  947. this.win.saveState();
  948. }
  949. });
  950. /**
  951. * @class Ext.WindowGroup
  952. * An object that manages a group of {@link Ext.Window} instances and provides z-order management
  953. * and window activation behavior.
  954. * @constructor
  955. */
  956. Ext.WindowGroup = function(){
  957. var list = {};
  958. var accessList = [];
  959. var front = null;
  960. // private
  961. var sortWindows = function(d1, d2){
  962. return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
  963. };
  964. // private
  965. var orderWindows = function(){
  966. var a = accessList, len = a.length;
  967. if(len > 0){
  968. a.sort(sortWindows);
  969. var seed = a[0].manager.zseed;
  970. for(var i = 0; i < len; i++){
  971. var win = a[i];
  972. if(win && !win.hidden){
  973. win.setZIndex(seed + (i*10));
  974. }
  975. }
  976. }
  977. activateLast();
  978. };
  979. // private
  980. var setActiveWin = function(win){
  981. if(win != front){
  982. if(front){
  983. front.setActive(false);
  984. }
  985. front = win;
  986. if(win){
  987. win.setActive(true);
  988. }
  989. }
  990. };
  991. // private
  992. var activateLast = function(){
  993. for(var i = accessList.length-1; i >=0; --i) {
  994. if(!accessList[i].hidden){
  995. setActiveWin(accessList[i]);
  996. return;
  997. }
  998. }
  999. // none to activate
  1000. setActiveWin(null);
  1001. };
  1002. return {
  1003. /**
  1004. * The starting z-index for windows in this WindowGroup (defaults to 9000)
  1005. * @type Number The z-index value
  1006. */
  1007. zseed : 9000,
  1008. /**
  1009. * <p>Registers a {@link Ext.Window Window} with this WindowManager. This should not
  1010. * need to be called under normal circumstances. Windows are automatically registered
  1011. * with a {@link Ext.Window#manager manager} at construction time.</p>
  1012. * <p>Where this may be useful is moving Windows between two WindowManagers. For example,
  1013. * to bring the Ext.MessageBox dialog under the same manager as the Desktop's
  1014. * WindowManager in the desktop sample app:</p><code><pre>
  1015. var msgWin = Ext.MessageBox.getDialog();
  1016. MyDesktop.getDesktop().getManager().register(msgWin);
  1017. </pre></code>
  1018. * @param {Window} win The Window to register.
  1019. */
  1020. register : function(win){
  1021. if(win.manager){
  1022. win.manager.unregister(win);
  1023. }
  1024. win.manager = this;
  1025. list[win.id] = win;
  1026. accessList.push(win);
  1027. win.on('hide', activateLast);
  1028. },
  1029. /**
  1030. * <p>Unregisters a {@link Ext.Window Window} from this WindowManager. This should not
  1031. * need to be called. Windows are automatically unregistered upon destruction.
  1032. * See {@link #register}.</p>
  1033. * @param {Window} win The Window to unregister.
  1034. */
  1035. unregister : function(win){
  1036. delete win.manager;
  1037. delete list[win.id];
  1038. win.un('hide', activateLast);
  1039. accessList.remove(win);
  1040. },
  1041. /**
  1042. * Gets a registered window by id.
  1043. * @param {String/Object} id The id of the window or a {@link Ext.Window} instance
  1044. * @return {Ext.Window}
  1045. */
  1046. get : function(id){
  1047. return typeof id == "object" ? id : list[id];
  1048. },
  1049. /**
  1050. * Brings the specified window to the front of any other active windows in this WindowGroup.
  1051. * @param {String/Object} win The id of the window or a {@link Ext.Window} instance
  1052. * @return {Boolean} True if the dialog was brought to the front, else false
  1053. * if it was already in front
  1054. */
  1055. bringToFront : function(win){
  1056. win = this.get(win);
  1057. if(win != front){
  1058. win._lastAccess = new Date().getTime();
  1059. orderWindows();
  1060. return true;
  1061. }
  1062. return false;
  1063. },
  1064. /**
  1065. * Sends the specified window to the back of other active windows in this WindowGroup.
  1066. * @param {String/Object} win The id of the window or a {@link Ext.Window} instance
  1067. * @return {Ext.Window} The window
  1068. */
  1069. sendToBack : function(win){
  1070. win = this.get(win);
  1071. win._lastAccess = -(new Date().getTime());
  1072. orderWindows();
  1073. return win;
  1074. },
  1075. /**
  1076. * Hides all windows in this WindowGroup.
  1077. */
  1078. hideAll : function(){
  1079. for(var id in list){
  1080. if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
  1081. list[id].hide();
  1082. }
  1083. }
  1084. },
  1085. /**
  1086. * Gets the currently-active window in this WindowGroup.
  1087. * @return {Ext.Window} The active window
  1088. */
  1089. getActive : function(){
  1090. return front;
  1091. },
  1092. /**
  1093. * Returns zero or more windows in this WindowGroup using the custom search function passed to this method.
  1094. * The function should accept a single {@link Ext.Window} reference as its only argument and should
  1095. * return true if the window matches the search criteria, otherwise it should return false.
  1096. * @param {Function} fn The search function
  1097. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the Window being tested.
  1098. * that gets passed to the function if not specified)
  1099. * @return {Array} An array of zero or more matching windows
  1100. */
  1101. getBy : function(fn, scope){
  1102. var r = [];
  1103. for(var i = accessList.length-1; i >=0; --i) {
  1104. var win = accessList[i];
  1105. if(fn.call(scope||win, win) !== false){
  1106. r.push(win);
  1107. }
  1108. }
  1109. return r;
  1110. },
  1111. /**
  1112. * Executes the specified function once for every window in this WindowGroup, passing each
  1113. * window as the only parameter. Returning false from the function will stop the iteration.
  1114. * @param {Function} fn The function to execute for each item
  1115. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the function is executed. Defaults to the current Window in the iteration.
  1116. */
  1117. each : function(fn, scope){
  1118. for(var id in list){
  1119. if(list[id] && typeof list[id] != "function"){
  1120. if(fn.call(scope || list[id], list[id]) === false){
  1121. return;
  1122. }
  1123. }
  1124. }
  1125. }
  1126. };
  1127. };
  1128. /**
  1129. * @class Ext.WindowMgr
  1130. * @extends Ext.WindowGroup
  1131. * The default global window group that is available automatically. To have more than one group of windows
  1132. * with separate z-order stacks, create additional instances of {@link Ext.WindowGroup} as needed.
  1133. * @singleton
  1134. */
  1135. Ext.WindowMgr = new Ext.WindowGroup();/**
  1136. * @class Ext.MessageBox
  1137. * <p>Utility class for generating different styles of message boxes. The alias Ext.Msg can also be used.<p/>
  1138. * <p>Note that the MessageBox is asynchronous. Unlike a regular JavaScript <code>alert</code> (which will halt
  1139. * browser execution), showing a MessageBox will not cause the code to stop. For this reason, if you have code
  1140. * that should only run <em>after</em> some user feedback from the MessageBox, you must use a callback function
  1141. * (see the <code>function</code> parameter for {@link #show} for more details).</p>
  1142. * <p>Example usage:</p>
  1143. *<pre><code>
  1144. // Basic alert:
  1145. Ext.Msg.alert('Status', 'Changes saved successfully.');
  1146. // Prompt for user data and process the result using a callback:
  1147. Ext.Msg.prompt('Name', 'Please enter your name:', function(btn, text){
  1148. if (btn == 'ok'){
  1149. // process text value and close...
  1150. }
  1151. });
  1152. // Show a dialog using config options:
  1153. Ext.Msg.show({
  1154. title:'Save Changes?',
  1155. msg: 'You are closing a tab that has unsaved changes. Would you like to save your changes?',
  1156. buttons: Ext.Msg.YESNOCANCEL,
  1157. fn: processResult,
  1158. animEl: 'elId',
  1159. icon: Ext.MessageBox.QUESTION
  1160. });
  1161. </code></pre>
  1162. * @singleton
  1163. */
  1164. Ext.MessageBox = function(){
  1165. var dlg, opt, mask, waitTimer,
  1166. bodyEl, msgEl, textboxEl, textareaEl, progressBar, pp, iconEl, spacerEl,
  1167. buttons, activeTextEl, bwidth, bufferIcon = '', iconCls = '',
  1168. buttonNames = ['ok', 'yes', 'no', 'cancel'];
  1169. // private
  1170. var handleButton = function(button){
  1171. buttons[button].blur();
  1172. if(dlg.isVisible()){
  1173. dlg.hide();
  1174. handleHide();
  1175. Ext.callback(opt.fn, opt.scope||window, [button, activeTextEl.dom.value, opt], 1);
  1176. }
  1177. };
  1178. // private
  1179. var handleHide = function(){
  1180. if(opt && opt.cls){
  1181. dlg.el.removeClass(opt.cls);
  1182. }
  1183. progressBar.reset();
  1184. };
  1185. // private
  1186. var handleEsc = function(d, k, e){
  1187. if(opt && opt.closable !== false){
  1188. dlg.hide();
  1189. handleHide();
  1190. }
  1191. if(e){
  1192. e.stopEvent();
  1193. }
  1194. };
  1195. // private
  1196. var updateButtons = function(b){
  1197. var width = 0,
  1198. cfg;
  1199. if(!b){
  1200. Ext.each(buttonNames, function(name){
  1201. buttons[name].hide();
  1202. });
  1203. return width;
  1204. }
  1205. dlg.footer.dom.style.display = '';
  1206. Ext.iterate(buttons, function(name, btn){
  1207. cfg = b[name];
  1208. if(cfg){
  1209. btn.show();
  1210. btn.setText(Ext.isString(cfg) ? cfg : Ext.MessageBox.buttonText[name]);
  1211. width += btn.getEl().getWidth() + 15;
  1212. }else{
  1213. btn.hide();
  1214. }
  1215. });
  1216. return width;
  1217. };
  1218. return {
  1219. /**
  1220. * Returns a reference to the underlying {@link Ext.Window} element
  1221. * @return {Ext.Window} The window
  1222. */
  1223. getDialog : function(titleText){
  1224. if(!dlg){
  1225. var btns = [];
  1226. buttons = {};
  1227. Ext.each(buttonNames, function(name){
  1228. btns.push(buttons[name] = new Ext.Button({
  1229. text: this.buttonText[name],
  1230. handler: handleButton.createCallback(name),
  1231. hideMode: 'offsets'
  1232. }));
  1233. }, this);
  1234. dlg = new Ext.Window({
  1235. autoCreate : true,
  1236. title:titleText,
  1237. resizable:false,
  1238. constrain:true,
  1239. constrainHeader:true,
  1240. minimizable : false,
  1241. maximizable : false,
  1242. stateful: false,
  1243. modal: true,
  1244. shim:true,
  1245. buttonAlign:"center",
  1246. width:400,
  1247. height:100,
  1248. minHeight: 80,
  1249. plain:true,
  1250. footer:true,
  1251. closable:true,
  1252. close : function(){
  1253. if(opt && opt.buttons && opt.buttons.no && !opt.buttons.cancel){
  1254. handleButton("no");
  1255. }else{
  1256. handleButton("cancel");
  1257. }
  1258. },
  1259. fbar: new Ext.Toolbar({
  1260. items: btns,
  1261. enableOverflow: false
  1262. })
  1263. });
  1264. dlg.render(document.body);
  1265. dlg.getEl().addClass('x-window-dlg');
  1266. mask = dlg.mask;
  1267. bodyEl = dlg.body.createChild({
  1268. html:'<div class="ext-mb-icon"></div><div class="ext-mb-content"><span class="ext-mb-text"></span><br /><div class="ext-mb-fix-cursor"><input type="text" class="ext-mb-input" /><textarea class="ext-mb-textarea"></textarea></div></div>'
  1269. });
  1270. iconEl = Ext.get(bodyEl.dom.firstChild);
  1271. var contentEl = bodyEl.dom.childNodes[1];
  1272. msgEl = Ext.get(contentEl.firstChild);
  1273. textboxEl = Ext.get(contentEl.childNodes[2].firstChild);
  1274. textboxEl.enableDisplayMode();
  1275. textboxEl.addKeyListener([10,13], function(){
  1276. if(dlg.isVisible() && opt && opt.buttons){
  1277. if(opt.buttons.ok){
  1278. handleButton("ok");
  1279. }else if(opt.buttons.yes){
  1280. handleButton("yes");
  1281. }
  1282. }
  1283. });
  1284. textareaEl = Ext.get(contentEl.childNodes[2].childNodes[1]);
  1285. textareaEl.enableDisplayMode();
  1286. progressBar = new Ext.ProgressBar({
  1287. renderTo:bodyEl
  1288. });
  1289. bodyEl.createChild({cls:'x-clear'});
  1290. }
  1291. return dlg;
  1292. },
  1293. /**
  1294. * Updates the message box body text
  1295. * @param {String} text (optional) Replaces the message box element's innerHTML with the specified string (defaults to
  1296. * the XHTML-compliant non-breaking space character '&amp;#160;')
  1297. * @return {Ext.MessageBox} this
  1298. */
  1299. updateText : function(text){
  1300. if(!dlg.isVisible() && !opt.width){
  1301. dlg.setSize(this.maxWidth, 100); // resize first so content is never clipped from previous shows
  1302. }
  1303. msgEl.update(text || '&#160;');
  1304. var iw = iconCls != '' ? (iconEl.getWidth() + iconEl.getMargins('lr')) : 0,
  1305. mw = msgEl.getWidth() + msgEl.getMargins('lr'),
  1306. fw = dlg.getFrameWidth('lr'),
  1307. bw = dlg.body.getFrameWidth('lr'),
  1308. w;
  1309. if (Ext.isIE && iw > 0){
  1310. //3 pixels get subtracted in the icon CSS for an IE margin issue,
  1311. //so we have to add it back here for the overall width to be consistent
  1312. iw += 3;
  1313. }
  1314. w = Math.max(Math.min(opt.width || iw+mw+fw+bw, opt.maxWidth || this.maxWidth),
  1315. Math.max(opt.minWidth || this.minWidth, bwidth || 0));
  1316. if(opt.prompt === true){
  1317. activeTextEl.setWidth(w-iw-fw-bw);
  1318. }
  1319. if(opt.progress === true || opt.wait === true){
  1320. progressBar.setSize(w-iw-fw-bw);
  1321. }
  1322. if(Ext.isIE && w == bwidth){
  1323. w += 4; //Add offset when the content width is smaller than the buttons.
  1324. }
  1325. dlg.setSize(w, 'auto').center();
  1326. return this;
  1327. },
  1328. /**
  1329. * Updates a progress-style message box's text and progress bar. Only relevant on message boxes
  1330. * initiated via {@link Ext.MessageBox#progress} or {@link Ext.MessageBox#wait},
  1331. * or by calling {@link Ext.MessageBox#show} with progress: true.
  1332. * @param {Number} value Any number between 0 and 1 (e.g., .5, defaults to 0)
  1333. * @param {String} progressText The progress text to display inside the progress bar (defaults to '')
  1334. * @param {String} msg The message box's body text is replaced with the specified string (defaults to undefined
  1335. * so that any existing body text will not get overwritten by default unless a new value is passed in)
  1336. * @return {Ext.MessageBox} this
  1337. */
  1338. updateProgress : function(value, progressText, msg){
  1339. progressBar.updateProgress(value, progressText);
  1340. if(msg){
  1341. this.updateText(msg);
  1342. }
  1343. return this;
  1344. },
  1345. /**
  1346. * Returns true if the message box is currently displayed
  1347. * @return {Boolean} True if the message box is visible, else false
  1348. */
  1349. isVisible : function(){
  1350. return dlg && dlg.isVisible();
  1351. },
  1352. /**
  1353. * Hides the message box if it is displayed
  1354. * @return {Ext.MessageBox} this
  1355. */
  1356. hide : function(){
  1357. var proxy = dlg ? dlg.activeGhost : null;
  1358. if(this.isVisible() || proxy){
  1359. dlg.hide();
  1360. handleHide();
  1361. if (proxy){
  1362. // unghost is a private function, but i saw no better solution
  1363. // to fix the locking problem when dragging while it closes
  1364. dlg.unghost(false, false);
  1365. }
  1366. }
  1367. return this;
  1368. },
  1369. /**
  1370. * Displays a new message box, or reinitializes an existing message box, based on the config options
  1371. * passed in. All display functions (e.g. prompt, alert, etc.) on MessageBox call this function internally,
  1372. * although those calls are basic shortcuts and do not support all of the config options allowed here.
  1373. * @param {Object} config The following config options are supported: <ul>
  1374. * <li><b>animEl</b> : String/Element<div class="sub-desc">An id or Element from which the message box should animate as it
  1375. * opens and closes (defaults to undefined)</div></li>
  1376. * <li><b>buttons</b> : Object/Boolean<div class="sub-desc">A button config object (e.g., Ext.MessageBox.OKCANCEL or {ok:'Foo',
  1377. * cancel:'Bar'}), or false to not show any buttons (defaults to false)</div></li>
  1378. * <li><b>closable</b> : Boolean<div class="sub-desc">False to hide the top-right close button (defaults to true). Note that
  1379. * progress and wait dialogs will ignore this property and always hide the close button as they can only
  1380. * be closed programmatically.</div></li>
  1381. * <li><b>cls</b> : String<div class="sub-desc">A custom CSS class to apply to the message box's container element</div></li>
  1382. * <li><b>defaultTextHeight</b> : Number<div class="sub-desc">The default height in pixels of the message box's multiline textarea
  1383. * if displayed (defaults to 75)</div></li>
  1384. * <li><b>fn</b> : Function<div class="sub-desc">A callback function which is called when the dialog is dismissed either
  1385. * by clicking on the configured buttons, or on the dialog close button, or by pressing
  1386. * the return button to enter input.
  1387. * <p>Progress and wait dialogs will ignore this option since they do not respond to user
  1388. * actions and can only be closed programmatically, so any required function should be called
  1389. * by the same code after it closes the dialog. Parameters passed:<ul>
  1390. * <li><b>buttonId</b> : String<div class="sub-desc">The ID of the button pressed, one of:<div class="sub-desc"><ul>
  1391. * <li><tt>ok</tt></li>
  1392. * <li><tt>yes</tt></li>
  1393. * <li><tt>no</tt></li>
  1394. * <li><tt>cancel</tt></li>
  1395. * </ul></div></div></li>
  1396. * <li><b>text</b> : String<div class="sub-desc">Value of the input field if either <tt><a href="#show-option-prompt" ext:member="show-option-prompt" ext:cls="Ext.MessageBox">prompt</a></tt>
  1397. * or <tt><a href="#show-option-multiline" ext:member="show-option-multiline" ext:cls="Ext.MessageBox">multiline</a></tt> is true</div></li>
  1398. * <li><b>opt</b> : Object<div class="sub-desc">The config object passed to show.</div></li>
  1399. * </ul></p></div></li>
  1400. * <li><b>scope</b> : Object<div class="sub-desc">The scope of the callback function</div></li>
  1401. * <li><b>icon</b> : String<div class="sub-desc">A CSS class that provides a background image to be used as the body icon for the
  1402. * dialog (e.g. Ext.MessageBox.WARNING or 'custom-class') (defaults to '')</div></li>
  1403. * <li><b>iconCls</b> : String<div class="sub-desc">The standard {@link Ext.Window#iconCls} to
  1404. * add an optional header icon (defaults to '')</div></li>
  1405. * <li><b>maxWidth</b> : Number<div class="sub-desc">The maximum width in pixels of the message box (defaults to 600)</div></li>
  1406. * <li><b>minWidth</b> : Number<div class="sub-desc">The minimum width in pixels of the message box (defaults to 100)</div></li>
  1407. * <li><b>modal</b> : Boolean<div class="sub-desc">False to allow user interaction with the page while the message box is
  1408. * displayed (defaults to true)</div></li>
  1409. * <li><b>msg</b> : String<div class="sub-desc">A string that will replace the existing message box body text (defaults to the
  1410. * XHTML-compliant non-breaking space character '&amp;#160;')</div></li>
  1411. * <li><a id="show-option-multiline"></a><b>multiline</b> : Boolean<div class="sub-desc">
  1412. * True to prompt the user to enter multi-line text (defaults to false)</div></li>
  1413. * <li><b>progress</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
  1414. * <li><b>progressText</b> : String<div class="sub-desc">The text to display inside the progress bar if progress = true (defaults to '')</div></li>
  1415. * <li><a id="show-option-prompt"></a><b>prompt</b> : Boolean<div class="sub-desc">True to prompt the user to enter single-line text (defaults to false)</div></li>
  1416. * <li><b>proxyDrag</b> : Boolean<div class="sub-desc">True to display a lightweight proxy while dragging (defaults to false)</div></li>
  1417. * <li><b>title</b> : String<div class="sub-desc">The title text</div></li>
  1418. * <li><b>value</b> : String<div class="sub-desc">The string value to set into the active textbox element if displayed</div></li>
  1419. * <li><b>wait</b> : Boolean<div class="sub-desc">True to display a progress bar (defaults to false)</div></li>
  1420. * <li><b>waitConfig</b> : Object<div class="sub-desc">A {@link Ext.ProgressBar#waitConfig} object (applies only if wait = true)</div></li>
  1421. * <li><b>width</b> : Number<div class="sub-desc">The width of the dialog in pixels</div></li>
  1422. * </ul>
  1423. * Example usage:
  1424. * <pre><code>
  1425. Ext.Msg.show({
  1426. title: 'Address',
  1427. msg: 'Please enter your address:',
  1428. width: 300,
  1429. buttons: Ext.MessageBox.OKCANCEL,
  1430. multiline: true,
  1431. fn: saveAddress,
  1432. animEl: 'addAddressBtn',
  1433. icon: Ext.MessageBox.INFO
  1434. });
  1435. </code></pre>
  1436. * @return {Ext.MessageBox} this
  1437. */
  1438. show : function(options){
  1439. if(this.isVisible()){
  1440. this.hide();
  1441. }
  1442. opt = options;
  1443. var d = this.getDialog(opt.title || "&#160;");
  1444. d.setTitle(opt.title || "&#160;");
  1445. var allowClose = (opt.closable !== false && opt.progress !== true && opt.wait !== true);
  1446. d.tools.close.setDisplayed(allowClose);
  1447. activeTextEl = textboxEl;
  1448. opt.prompt = opt.prompt || (opt.multiline ? true : false);
  1449. if(opt.prompt){
  1450. if(opt.multiline){
  1451. textboxEl.hide();
  1452. textareaEl.show();
  1453. textareaEl.setHeight(Ext.isNumber(opt.multiline) ? opt.multiline : this.defaultTextHeight);
  1454. activeTextEl = textareaEl;
  1455. }else{
  1456. textboxEl.show();
  1457. textareaEl.hide();
  1458. }
  1459. }else{
  1460. textboxEl.hide();
  1461. textareaEl.hide();
  1462. }
  1463. activeTextEl.dom.value = opt.value || "";
  1464. if(opt.prompt){
  1465. d.focusEl = activeTextEl;
  1466. }else{
  1467. var bs = opt.buttons;
  1468. var db = null;
  1469. if(bs && bs.ok){
  1470. db = buttons["ok"];
  1471. }else if(bs && bs.yes){
  1472. db = buttons["yes"];
  1473. }
  1474. if (db){
  1475. d.focusEl = db;
  1476. }
  1477. }
  1478. if(opt.iconCls){
  1479. d.setIconClass(opt.iconCls);
  1480. }
  1481. this.setIcon(Ext.isDefined(opt.icon) ? opt.icon : bufferIcon);
  1482. bwidth = updateButtons(opt.buttons);
  1483. progressBar.setVisible(opt.progress === true || opt.wait === true);
  1484. this.updateProgress(0, opt.progressText);
  1485. this.updateText(opt.msg);
  1486. if(opt.cls){
  1487. d.el.addClass(opt.cls);
  1488. }
  1489. d.proxyDrag = opt.proxyDrag === true;
  1490. d.modal = opt.modal !== false;
  1491. d.mask = opt.modal !== false ? mask : false;
  1492. if(!d.isVisible()){
  1493. // force it to the end of the z-index stack so it gets a cursor in FF
  1494. document.body.appendChild(dlg.el.dom);
  1495. d.setAnimateTarget(opt.animEl);
  1496. //workaround for window internally enabling keymap in afterShow
  1497. d.on('show', function(){
  1498. if(allowClose === true){
  1499. d.keyMap.enable();
  1500. }else{
  1501. d.keyMap.disable();
  1502. }
  1503. }, this, {single:true});
  1504. d.show(opt.animEl);
  1505. }
  1506. if(opt.wait === true){
  1507. progressBar.wait(opt.waitConfig);
  1508. }
  1509. return this;
  1510. },
  1511. /**
  1512. * Adds the specified icon to the dialog. By default, the class 'ext-mb-icon' is applied for default
  1513. * styling, and the class passed in is expected to supply the background image url. Pass in empty string ('')
  1514. * to clear any existing icon. This method must be called before the MessageBox is shown.
  1515. * The following built-in icon classes are supported, but you can also pass in a custom class name:
  1516. * <pre>
  1517. Ext.MessageBox.INFO
  1518. Ext.MessageBox.WARNING
  1519. Ext.MessageBox.QUESTION
  1520. Ext.MessageBox.ERROR
  1521. *</pre>
  1522. * @param {String} icon A CSS classname specifying the icon's background image url, or empty string to clear the icon
  1523. * @return {Ext.MessageBox} this
  1524. */
  1525. setIcon : function(icon){
  1526. if(!dlg){
  1527. bufferIcon = icon;
  1528. return;
  1529. }
  1530. bufferIcon = undefined;
  1531. if(icon && icon != ''){
  1532. iconEl.removeClass('x-hidden');
  1533. iconEl.replaceClass(iconCls, icon);
  1534. bodyEl.addClass('x-dlg-icon');
  1535. iconCls = icon;
  1536. }else{
  1537. iconEl.replaceClass(iconCls, 'x-hidden');
  1538. bodyEl.removeClass('x-dlg-icon');
  1539. iconCls = '';
  1540. }
  1541. return this;
  1542. },
  1543. /**
  1544. * Displays a message box with a progress bar. This message box has no buttons and is not closeable by
  1545. * the user. You are responsible for updating the progress bar as needed via {@link Ext.MessageBox#updateProgress}
  1546. * and closing the message box when the process is complete.
  1547. * @param {String} title The title bar text
  1548. * @param {String} msg The message box body text
  1549. * @param {String} progressText (optional) The text to display inside the progress bar (defaults to '')
  1550. * @return {Ext.MessageBox} this
  1551. */
  1552. progress : function(title, msg, progressText){
  1553. this.show({
  1554. title : title,
  1555. msg : msg,
  1556. buttons: false,
  1557. progress:true,
  1558. closable:false,
  1559. minWidth: this.minProgressWidth,
  1560. progressText: progressText
  1561. });
  1562. return this;
  1563. },
  1564. /**
  1565. * Displays a message box with an infinitely auto-updating progress bar. This can be used to block user
  1566. * interaction while waiting for a long-running process to complete that does not have defined intervals.
  1567. * You are responsible for closing the message box when the process is complete.
  1568. * @param {String} msg The message box body text
  1569. * @param {String} title (optional) The title bar text
  1570. * @param {Object} config (optional) A {@link Ext.ProgressBar#waitConfig} object
  1571. * @return {Ext.MessageBox} this
  1572. */
  1573. wait : function(msg, title, config){
  1574. this.show({
  1575. title : title,
  1576. msg : msg,
  1577. buttons: false,
  1578. closable:false,
  1579. wait:true,
  1580. modal:true,
  1581. minWidth: this.minProgressWidth,
  1582. waitConfig: config
  1583. });
  1584. return this;
  1585. },
  1586. /**
  1587. * Displays a standard read-only message box with an OK button (comparable to the basic JavaScript alert prompt).
  1588. * If a callback function is passed it will be called after the user clicks the button, and the
  1589. * id of the button that was clicked will be passed as the only parameter to the callback
  1590. * (could also be the top-right close button).
  1591. * @param {String} title The title bar text
  1592. * @param {String} msg The message box body text
  1593. * @param {Function} fn (optional) The callback function invoked after the message box is closed
  1594. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
  1595. * @return {Ext.MessageBox} this
  1596. */
  1597. alert : function(title, msg, fn, scope){
  1598. this.show({
  1599. title : title,
  1600. msg : msg,
  1601. buttons: this.OK,
  1602. fn: fn,
  1603. scope : scope,
  1604. minWidth: this.minWidth
  1605. });
  1606. return this;
  1607. },
  1608. /**
  1609. * Displays a confirmation message box with Yes and No buttons (comparable to JavaScript's confirm).
  1610. * If a callback function is passed it will be called after the user clicks either button,
  1611. * and the id of the button that was clicked will be passed as the only parameter to the callback
  1612. * (could also be the top-right close button).
  1613. * @param {String} title The title bar text
  1614. * @param {String} msg The message box body text
  1615. * @param {Function} fn (optional) The callback function invoked after the message box is closed
  1616. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
  1617. * @return {Ext.MessageBox} this
  1618. */
  1619. confirm : function(title, msg, fn, scope){
  1620. this.show({
  1621. title : title,
  1622. msg : msg,
  1623. buttons: this.YESNO,
  1624. fn: fn,
  1625. scope : scope,
  1626. icon: this.QUESTION,
  1627. minWidth: this.minWidth
  1628. });
  1629. return this;
  1630. },
  1631. /**
  1632. * Displays a message box with OK and Cancel buttons prompting the user to enter some text (comparable to JavaScript's prompt).
  1633. * The prompt can be a single-line or multi-line textbox. If a callback function is passed it will be called after the user
  1634. * clicks either button, and the id of the button that was clicked (could also be the top-right
  1635. * close button) and the text that was entered will be passed as the two parameters to the callback.
  1636. * @param {String} title The title bar text
  1637. * @param {String} msg The message box body text
  1638. * @param {Function} fn (optional) The callback function invoked after the message box is closed
  1639. * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the callback is executed. Defaults to the browser wnidow.
  1640. * @param {Boolean/Number} multiline (optional) True to create a multiline textbox using the defaultTextHeight
  1641. * property, or the height in pixels to create the textbox (defaults to false / single-line)
  1642. * @param {String} value (optional) Default value of the text input element (defaults to '')
  1643. * @return {Ext.MessageBox} this
  1644. */
  1645. prompt : function(title, msg, fn, scope, multiline, value){
  1646. this.show({
  1647. title : title,
  1648. msg : msg,
  1649. buttons: this.OKCANCEL,
  1650. fn: fn,
  1651. minWidth: this.minPromptWidth,
  1652. scope : scope,
  1653. prompt:true,
  1654. multiline: multiline,
  1655. value: value
  1656. });
  1657. return this;
  1658. },
  1659. /**
  1660. * Button config that displays a single OK button
  1661. * @type Object
  1662. */
  1663. OK : {ok:true},
  1664. /**
  1665. * Button config that displays a single Cancel button
  1666. * @type Object
  1667. */
  1668. CANCEL : {cancel:true},
  1669. /**
  1670. * Button config that displays OK and Cancel buttons
  1671. * @type Object
  1672. */
  1673. OKCANCEL : {ok:true, cancel:true},
  1674. /**
  1675. * Button config that displays Yes and No buttons
  1676. * @type Object
  1677. */
  1678. YESNO : {yes:true, no:true},
  1679. /**
  1680. * Button config that displays Yes, No and Cancel buttons
  1681. * @type Object
  1682. */
  1683. YESNOCANCEL : {yes:true, no:true, cancel:true},
  1684. /**
  1685. * The CSS class that provides the INFO icon image
  1686. * @type String
  1687. */
  1688. INFO : 'ext-mb-info',
  1689. /**
  1690. * The CSS class that provides the WARNING icon image
  1691. * @type String
  1692. */
  1693. WARNING : 'ext-mb-warning',
  1694. /**
  1695. * The CSS class that provides the QUESTION icon image
  1696. * @type String
  1697. */
  1698. QUESTION : 'ext-mb-question',
  1699. /**
  1700. * The CSS class that provides the ERROR icon image
  1701. * @type String
  1702. */
  1703. ERROR : 'ext-mb-error',
  1704. /**
  1705. * The default height in pixels of the message box's multiline textarea if displayed (defaults to 75)
  1706. * @type Number
  1707. */
  1708. defaultTextHeight : 75,
  1709. /**
  1710. * The maximum width in pixels of the message box (defaults to 600)
  1711. * @type Number
  1712. */
  1713. maxWidth : 600,
  1714. /**
  1715. * The minimum width in pixels of the message box (defaults to 100)
  1716. * @type Number
  1717. */
  1718. minWidth : 100,
  1719. /**
  1720. * The minimum width in pixels of the message box if it is a progress-style dialog. This is useful
  1721. * for setting a different minimum width than text-only dialogs may need (defaults to 250).
  1722. * @type Number
  1723. */
  1724. minProgressWidth : 250,
  1725. /**
  1726. * The minimum width in pixels of the message box if it is a prompt dialog. This is useful
  1727. * for setting a different minimum width than text-only dialogs may need (defaults to 250).
  1728. * @type Number
  1729. */
  1730. minPromptWidth: 250,
  1731. /**
  1732. * An object containing the default button text strings that can be overriden for localized language support.
  1733. * Supported properties are: ok, cancel, yes and no. Generally you should include a locale-specific
  1734. * resource file for handling language support across the framework.
  1735. * Customize the default text like so: Ext.MessageBox.buttonText.yes = "oui"; //french
  1736. * @type Object
  1737. */
  1738. buttonText : {
  1739. ok : "OK",
  1740. cancel : "Cancel",
  1741. yes : "Yes",
  1742. no : "No"
  1743. }
  1744. };
  1745. }();
  1746. /**
  1747. * Shorthand for {@link Ext.MessageBox}
  1748. */
  1749. Ext.Msg = Ext.MessageBox;/**
  1750. * @class Ext.dd.PanelProxy
  1751. * A custom drag proxy implementation specific to {@link Ext.Panel}s. This class is primarily used internally
  1752. * for the Panel's drag drop implementation, and should never need to be created directly.
  1753. * @constructor
  1754. * @param panel The {@link Ext.Panel} to proxy for
  1755. * @param config Configuration options
  1756. */
  1757. Ext.dd.PanelProxy = function(panel, config){
  1758. this.panel = panel;
  1759. this.id = this.panel.id +'-ddproxy';
  1760. Ext.apply(this, config);
  1761. };
  1762. Ext.dd.PanelProxy.prototype = {
  1763. /**
  1764. * @cfg {Boolean} insertProxy True to insert a placeholder proxy element while dragging the panel,
  1765. * false to drag with no proxy (defaults to true).
  1766. */
  1767. insertProxy : true,
  1768. // private overrides
  1769. setStatus : Ext.emptyFn,
  1770. reset : Ext.emptyFn,
  1771. update : Ext.emptyFn,
  1772. stop : Ext.emptyFn,
  1773. sync: Ext.emptyFn,
  1774. /**
  1775. * Gets the proxy's element
  1776. * @return {Element} The proxy's element
  1777. */
  1778. getEl : function(){
  1779. return this.ghost;
  1780. },
  1781. /**
  1782. * Gets the proxy's ghost element
  1783. * @return {Element} The proxy's ghost element
  1784. */
  1785. getGhost : function(){
  1786. return this.ghost;
  1787. },
  1788. /**
  1789. * Gets the proxy's element
  1790. * @return {Element} The proxy's element
  1791. */
  1792. getProxy : function(){
  1793. return this.proxy;
  1794. },
  1795. /**
  1796. * Hides the proxy
  1797. */
  1798. hide : function(){
  1799. if(this.ghost){
  1800. if(this.proxy){
  1801. this.proxy.remove();
  1802. delete this.proxy;
  1803. }
  1804. this.panel.el.dom.style.display = '';
  1805. this.ghost.remove();
  1806. delete this.ghost;
  1807. }
  1808. },
  1809. /**
  1810. * Shows the proxy
  1811. */
  1812. show : function(){
  1813. if(!this.ghost){
  1814. this.ghost = this.panel.createGhost(undefined, undefined, Ext.getBody());
  1815. this.ghost.setXY(this.panel.el.getXY());
  1816. if(this.insertProxy){
  1817. this.proxy = this.panel.el.insertSibling({cls:'x-panel-dd-spacer'});
  1818. this.proxy.setSize(this.panel.getSize());
  1819. }
  1820. this.panel.el.dom.style.display = 'none';
  1821. }
  1822. },
  1823. // private
  1824. repair : function(xy, callback, scope){
  1825. this.hide();
  1826. if(typeof callback == "function"){
  1827. callback.call(scope || this);
  1828. }
  1829. },
  1830. /**
  1831. * Moves the proxy to a different position in the DOM. This is typically called while dragging the Panel
  1832. * to keep the proxy sync'd to the Panel's location.
  1833. * @param {HTMLElement} parentNode The proxy's parent DOM node
  1834. * @param {HTMLElement} before (optional) The sibling node before which the proxy should be inserted (defaults
  1835. * to the parent's last child if not specified)
  1836. */
  1837. moveProxy : function(parentNode, before){
  1838. if(this.proxy){
  1839. parentNode.insertBefore(this.proxy.dom, before);
  1840. }
  1841. }
  1842. };
  1843. // private - DD implementation for Panels
  1844. Ext.Panel.DD = function(panel, cfg){
  1845. this.panel = panel;
  1846. this.dragData = {panel: panel};
  1847. this.proxy = new Ext.dd.PanelProxy(panel, cfg);
  1848. Ext.Panel.DD.superclass.constructor.call(this, panel.el, cfg);
  1849. var h = panel.header;
  1850. if(h){
  1851. this.setHandleElId(h.id);
  1852. }
  1853. (h ? h : this.panel.body).setStyle('cursor', 'move');
  1854. this.scroll = false;
  1855. };
  1856. Ext.extend(Ext.Panel.DD, Ext.dd.DragSource, {
  1857. showFrame: Ext.emptyFn,
  1858. startDrag: Ext.emptyFn,
  1859. b4StartDrag: function(x, y) {
  1860. this.proxy.show();
  1861. },
  1862. b4MouseDown: function(e) {
  1863. var x = e.getPageX();
  1864. var y = e.getPageY();
  1865. this.autoOffset(x, y);
  1866. },
  1867. onInitDrag : function(x, y){
  1868. this.onStartDrag(x, y);
  1869. return true;
  1870. },
  1871. createFrame : Ext.emptyFn,
  1872. getDragEl : function(e){
  1873. return this.proxy.ghost.dom;
  1874. },
  1875. endDrag : function(e){
  1876. this.proxy.hide();
  1877. this.panel.saveState();
  1878. },
  1879. autoOffset : function(x, y) {
  1880. x -= this.startPageX;
  1881. y -= this.startPageY;
  1882. this.setDelta(x, y);
  1883. }
  1884. });