3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * A specialized panel intended for use as an application window. Windows are floated, {@link #resizable}, and
17 * {@link #draggable} by default. Windows can be {@link #maximizable maximized} to fill the viewport, restored to
18 * their prior size, and can be {@link #minimize}d.
20 * Windows can also be linked to a {@link Ext.ZIndexManager} or managed by the {@link Ext.WindowManager} to provide
21 * grouping, activation, to front, to back and other application-specific behavior.
23 * By default, Windows will be rendered to document.body. To {@link #constrain} a Window to another element specify
24 * {@link Ext.Component#renderTo renderTo}.
26 * **As with all {@link Ext.container.Container Container}s, it is important to consider how you want the Window to size
27 * and arrange any child Components. Choose an appropriate {@link #layout} configuration which lays out child Components
28 * in the required manner.**
31 * Ext.create('Ext.window.Window', {
36 * items: { // Let's put an empty grid in just to illustrate fit layout
39 * columns: [{header: 'World'}], // One header just for show. There's no data,
40 * store: Ext.create('Ext.data.ArrayStore', {}) // A dummy empty data store
44 Ext.define('Ext.window.Window', {
45 extend: 'Ext.panel.Panel',
47 alternateClassName: 'Ext.Window',
49 requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
51 alias: 'widget.window',
55 * The X position of the left edge of the window on initial showing. Defaults to centering the Window within the
56 * width of the Window's container {@link Ext.Element Element} (The Element that the Window is rendered to).
61 * The Y position of the top edge of the window on initial showing. Defaults to centering the Window within the
62 * height of the Window's container {@link Ext.Element Element} (The Element that the Window is rendered to).
66 * @cfg {Boolean} [modal=false]
67 * True to make the window modal and mask everything behind it when displayed, false to display it without
68 * restricting access to other UI elements.
72 * @cfg {String/Ext.Element} [animateTarget=null]
73 * Id or element from which the window should animate while opening.
77 * @cfg {String/Number/Ext.Component} defaultFocus
78 * Specifies a Component to receive focus when this Window is focused.
82 * - The index of a footer Button.
83 * - The id or {@link Ext.AbstractComponent#itemId} of a descendant Component.
88 * @cfg {Function} onEsc
89 * Allows override of the built-in processing for the escape key. Default action is to close the Window (performing
90 * whatever action is specified in {@link #closeAction}. To prevent the Window closing when the escape key is
91 * pressed, specify this as {@link Ext#emptyFn Ext.emptyFn}.
95 * @cfg {Boolean} [collapsed=false]
96 * True to render the window collapsed, false to render it expanded. Note that if {@link #expandOnShow}
97 * is true (the default) it will override the `collapsed` config and the window will always be
98 * expanded when shown.
102 * @cfg {Boolean} [maximized=false]
103 * True to initially display the window in a maximized state.
107 * @cfg {String} [baseCls='x-window']
108 * The base CSS class to apply to this panel's element.
110 baseCls: Ext.baseCSSPrefix + 'window',
113 * @cfg {Boolean/Object} resizable
114 * Specify as `true` to allow user resizing at each edge and corner of the window, false to disable resizing.
116 * This may also be specified as a config object to Ext.resizer.Resizer
121 * @cfg {Boolean} draggable
122 * True to allow the window to be dragged by the header bar, false to disable dragging. Note that
123 * by default the window will be centered in the viewport, so if dragging is disabled the window may need to be
124 * positioned programmatically after render (e.g., myWindow.setPosition(100, 100);).
129 * @cfg {Boolean} constrain
130 * True to constrain the window within its containing element, false to allow it to fall outside of its containing
131 * element. By default the window will be rendered to document.body. To render and constrain the window within
132 * another element specify {@link #renderTo}. Optionally the header only can be constrained
133 * using {@link #constrainHeader}.
138 * @cfg {Boolean} constrainHeader
139 * True to constrain the window header within its containing element (allowing the window body to fall outside of
140 * its containing element) or false to allow the header to fall outside its containing element.
141 * Optionally the entire window can be constrained using {@link #constrain}.
143 constrainHeader: false,
146 * @cfg {Boolean} plain
147 * True to render the window body with a transparent background so that it will blend into the framing elements,
148 * false to add a lighter background color to visually highlight the body element and separate it more distinctly
149 * from the surrounding frame.
154 * @cfg {Boolean} minimizable
155 * True to display the 'minimize' tool button and allow the user to minimize the window, false to hide the button
156 * and disallow minimizing the window. Note that this button provides no implementation -- the
157 * behavior of minimizing a window is implementation-specific, so the minimize event must be handled and a custom
158 * minimize behavior implemented for this option to be useful.
163 * @cfg {Boolean} maximizable
164 * True to display the 'maximize' tool button and allow the user to maximize the window, false to hide the button
165 * and disallow maximizing the window. Note that when a window is maximized, the tool button
166 * will automatically change to a 'restore' button with the appropriate behavior already built-in that will restore
167 * the window to its previous size.
178 * @cfg {Boolean} expandOnShow
179 * True to always expand the window when it is displayed, false to keep it in its current state (which may be
180 * {@link #collapsed}) when displayed.
184 // inherited docs, same default
188 * @cfg {Boolean} closable
189 * True to display the 'close' tool button and allow the user to close the window, false to hide the button and
190 * disallow closing the window.
192 * By default, when close is requested by either clicking the close button in the header or pressing ESC when the
193 * Window has focus, the {@link #close} method will be called. This will _{@link Ext.Component#destroy destroy}_ the
194 * Window and its content meaning that it may not be reused.
196 * To make closing a Window _hide_ the Window so that it may be reused, set {@link #closeAction} to 'hide'.
201 * @cfg {Boolean} hidden
202 * Render this Window hidden. If `true`, the {@link #hide} method will be called internally.
206 // Inherit docs from Component. Windows render to the body on first show.
209 // Inherit docs from Component. Windows hide using visibility.
210 hideMode: 'visibility',
212 /** @cfg {Boolean} floating @hide Windows are always floating*/
215 ariaRole: 'alertdialog',
217 itemCls: 'x-window-item',
221 ignoreHeaderBorderManagement: true,
224 initComponent: function() {
230 * Fires after the window has been visually activated via {@link #setActive}.
231 * @param {Ext.window.Window} this
236 * Fires after the window has been visually deactivated via {@link #setActive}.
237 * @param {Ext.window.Window} this
242 * Fires after the window has been resized.
243 * @param {Ext.window.Window} this
244 * @param {Number} width The window's new width
245 * @param {Number} height The window's new height
251 * Fires after the window has been maximized.
252 * @param {Ext.window.Window} this
258 * Fires after the window has been minimized.
259 * @param {Ext.window.Window} this
265 * Fires after the window has been restored to its original size after being maximized.
266 * @param {Ext.window.Window} this
272 me.addClsWithUI('plain');
276 me.ariaRole = 'dialog';
283 initStateEvents: function(){
284 var events = this.stateEvents;
285 // push on stateEvents if they don't exist
286 Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
287 if (Ext.Array.indexOf(events, event)) {
294 getState: function() {
296 state = me.callParent() || {},
297 maximized = !!me.maximized;
299 state.maximized = maximized;
301 size: maximized ? me.restoreSize : me.getSize(),
302 pos: maximized ? me.restorePos : me.getPosition()
307 applyState: function(state){
311 me.maximized = state.maximized;
313 me.hasSavedRestore = true;
314 me.restoreSize = state.size;
315 me.restorePos = state.pos;
318 width: state.size.width,
319 height: state.size.height,
328 onMouseDown: function (e) {
332 if (Ext.fly(e.getTarget()).focusable()) {
335 this.toFront(preventFocus);
340 onRender: function(ct, position) {
342 me.callParent(arguments);
345 // Double clicking a header will toggleMaximize
346 if (me.maximizable) {
349 fn: me.toggleMaximize,
358 afterRender: function() {
364 // Component's afterRender sizes and positions the Component
368 // Create the proxy after the size has been applied in Component.afterRender
369 me.proxy = me.getProxy();
372 me.mon(me.el, 'mousedown', me.onMouseDown, me);
374 // allow the element to be focusable
381 me.maximized = false;
386 keyMap = me.getKeyMap();
387 keyMap.on(27, me.onEsc, me);
389 //if (hidden) { ? would be consistent w/before/afterShow...
395 me.syncMonitorWindowResize();
403 * Override Component.initDraggable.
404 * Window uses the header element as the delegate.
406 initDraggable: function() {
411 me.updateHeader(true);
415 * Check the header here again. If for whatever reason it wasn't created in
416 * updateHeader (preventHeader) then we'll just ignore the rest since the
417 * header acts as the drag handle.
420 ddConfig = Ext.applyIf({
422 delegate: '#' + me.header.id
425 // Add extra configs if Window is specified to be constrained
426 if (me.constrain || me.constrainHeader) {
427 ddConfig.constrain = me.constrain;
428 ddConfig.constrainDelegate = me.constrainHeader;
429 ddConfig.constrainTo = me.constrainTo || me.container;
433 * @property {Ext.util.ComponentDragger} dd
434 * If this Window is configured {@link #draggable}, this property will contain an instance of
435 * {@link Ext.util.ComponentDragger} (A subclass of {@link Ext.dd.DragTracker DragTracker}) which handles dragging
436 * the Window's DOM Element, and constraining according to the {@link #constrain} and {@link #constrainHeader} .
438 * This has implementations of `onBeforeStart`, `onDrag` and `onEnd` which perform the dragging action. If
439 * extra logic is needed at these points, use {@link Ext.Function#createInterceptor createInterceptor} or
440 * {@link Ext.Function#createSequence createSequence} to augment the existing implementations.
442 me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
443 me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
448 onEsc: function(k, e) {
450 this[this.closeAction]();
454 beforeDestroy: function() {
457 delete this.animateTarget;
469 * Contribute class-specific tools to the header.
470 * Called by Panel's initTools.
472 addTools: function() {
475 // Call Panel's initTools
478 if (me.minimizable) {
481 handler: Ext.Function.bind(me.minimize, me, [])
484 if (me.maximizable) {
487 handler: Ext.Function.bind(me.maximize, me, [])
491 handler: Ext.Function.bind(me.restore, me, []),
498 * Gets the configured default focus item. If a {@link #defaultFocus} is set, it will receive focus, otherwise the
499 * Container itself will receive focus.
501 getFocusEl: function() {
504 defaultComp = me.defaultButton || me.defaultFocus,
509 if (Ext.isDefined(defaultComp)) {
510 if (Ext.isNumber(defaultComp)) {
511 f = me.query('button')[defaultComp];
512 } else if (Ext.isString(defaultComp)) {
513 f = me.down('#' + defaultComp);
518 return f || me.focusEl;
522 beforeShow: function() {
525 if (this.expandOnShow) {
531 afterShow: function(animateTarget) {
533 animating = animateTarget || me.animateTarget;
536 // No constraining code needs to go here.
537 // Component.onShow constrains the Component. *If the constrain config is true*
539 // Perform superclass's afterShow tasks
540 // Which might include animating a proxy from an animateTarget
541 me.callParent(arguments);
547 me.syncMonitorWindowResize();
558 doClose: function() {
561 // Being called as callback after going through the hide call below
563 me.fireEvent('close', me);
564 if (me.closeAction == 'destroy') {
568 // close after hiding
569 me.hide(me.animateTarget, me.doClose, me);
574 afterHide: function() {
577 // No longer subscribe to resizing now that we're hidden
578 me.syncMonitorWindowResize();
580 // Turn off keyboard handling once window is hidden
585 // Perform superclass's afterHide tasks.
586 me.callParent(arguments);
590 onWindowResize: function() {
591 if (this.maximized) {
598 * Placeholder method for minimizing the window. By default, this method simply fires the {@link #minimize} event
599 * since the behavior of minimizing a window is application-specific. To implement custom minimize behavior, either
600 * the minimize event can be handled or this method can be overridden.
601 * @return {Ext.window.Window} this
603 minimize: function() {
604 this.fireEvent('minimize', this);
608 afterCollapse: function() {
611 if (me.maximizable) {
612 me.tools.maximize.hide();
613 me.tools.restore.hide();
616 me.resizer.disable();
618 me.callParent(arguments);
621 afterExpand: function() {
625 me.tools.restore.show();
626 } else if (me.maximizable) {
627 me.tools.maximize.show();
632 me.callParent(arguments);
636 * Fits the window within its current container and automatically replaces the {@link #maximizable 'maximize' tool
637 * button} with the 'restore' tool button. Also see {@link #toggleMaximize}.
638 * @return {Ext.window.Window} this
640 maximize: function() {
645 if (!me.hasSavedRestore) {
646 me.restoreSize = me.getSize();
647 me.restorePos = me.getPosition(true);
649 if (me.maximizable) {
650 me.tools.maximize.hide();
651 me.tools.restore.show();
654 me.el.disableShadow();
659 if (me.collapseTool) {
660 me.collapseTool.hide();
662 me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
663 me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
665 me.syncMonitorWindowResize();
666 me.setPosition(0, 0);
668 me.fireEvent('maximize', me);
674 * Restores a {@link #maximizable maximized} window back to its original size and position prior to being maximized
675 * and also replaces the 'restore' tool button with the 'maximize' tool button. Also see {@link #toggleMaximize}.
676 * @return {Ext.window.Window} this
678 restore: function() {
683 delete me.hasSavedRestore;
684 me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
686 // Toggle tool visibility
688 tools.restore.hide();
690 if (tools.maximize) {
691 tools.maximize.show();
693 if (me.collapseTool) {
694 me.collapseTool.show();
697 // Restore the position/sizing
698 me.setPosition(me.restorePos);
699 me.setSize(me.restoreSize);
701 // Unset old position/sizing
702 delete me.restorePos;
703 delete me.restoreSize;
705 me.maximized = false;
707 me.el.enableShadow(true);
709 // Allow users to drag and drop again
714 me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
716 me.syncMonitorWindowResize();
718 me.fireEvent('restore', me);
724 * Synchronizes the presence of our listener for window resize events. This method
725 * should be called whenever this status might change.
728 syncMonitorWindowResize: function () {
730 currentlyMonitoring = me._monitoringResize,
731 // all the states where we should be listening to window resize:
732 yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized,
733 // all the states where we veto this:
734 veto = me.hidden || me.destroying || me.isDestroyed;
737 // we should be listening...
738 if (!currentlyMonitoring) {
739 // but we aren't, so set it up
740 Ext.EventManager.onWindowResize(me.onWindowResize, me);
741 me._monitoringResize = true;
743 } else if (currentlyMonitoring) {
744 // we should not be listening, but we are, so tear it down
745 Ext.EventManager.removeResizeListener(me.onWindowResize, me);
746 me._monitoringResize = false;
751 * A shortcut method for toggling between {@link #maximize} and {@link #restore} based on the current maximized
752 * state of the window.
753 * @return {Ext.window.Window} this
755 toggleMaximize: function() {
756 return this[this.maximized ? 'restore': 'maximize']();
760 * @cfg {Boolean} autoWidth @hide
761 * Absolute positioned element and therefore cannot support autoWidth.
762 * A width is a required configuration.