13

If I create a modal window:

Ext.define('myWindow', {
    extend: 'Ext.Container',
    alias: 'widget.myWindow',
    floating: true,
    modal: true,
    listeners:
        'onMaskClick???': { close the window }
    .....
}

How do I know when a user has clicked on the mask outside the window? In Sench Touch, there is a config hideOnMaskTap that lets me specify. What is the event/config for extJS?

johnstoecker
  • 248
  • 1
  • 2
  • 7

4 Answers4

18

Tramway's case (sort of) works on modal or non modal windows. But not in case child components like the boundlist of a combobox float outside the windows boundaries.

However if you use modal windows anyway you can listen for a click event on the mask like this.

Ext.define('myWindow', {
    extend: 'Ext.window.Window',
    alias: 'widget.myWindow',
    floating: true,
    modal: true,

    initComponent: function () {
        var me = this;
        me.callParent(arguments);
        me.mon(Ext.getBody(), 'click', function(el, e){
            me.close(me.closeAction);
        }, me, { delegate: '.x-mask' });
    }
});
VDP
  • 6,340
  • 4
  • 31
  • 53
  • 1
    This is the correct answer and very clever to use a delegate. The window must anyway be modal because otherwise it would be strange for it to close when the user interacts with another window. Modal windows have a visual cue to suggest this to the user. – jjrv Mar 25 '13 at 06:19
  • 1
    shouldn't the first line of the `initComponent` function be `var me = this;` ? – Geo Jun 11 '13 at 15:48
  • Good solution, there's just one thing missing - you should extend [Ext.window.Window](http://docs-origin.sencha.com/extjs/4.1.0/#!/api/Ext.window.Window), not just the base Container, otherwise you will be missing everything from [Panel](http://docs-origin.sencha.com/extjs/4.1.0/#!/api/Ext.panel.Panel) and Window classes: `extend: 'Ext.window.Window',` – Mike Demenok Aug 25 '13 at 22:10
  • What is the tip if you have a windows without modal, you can't use : 'x-mask'. – John Paul Cárdenas Feb 02 '15 at 22:41
  • Like jjrv said: 'The window must anyway be modal because otherwise it would be strange for it to close when the user interacts with another window. Modal windows have a visual cue to suggest this to the user.' Why don't you want to make it modal? and if you really don't want to see the mask just set its opacity to 0 – VDP Feb 03 '15 at 12:24
  • Excellent answer. I especially like the use of `mon`. – MarthyM Jul 31 '17 at 08:59
11

You can listen all click events, then check if click position is out of the window

Ext.define('myWindow', {
    extend: 'Ext.Container',
    alias: 'widget.myWindow',
    floating: true,
    modal: true,

    initComponent: function () {
        this.initEvents();
        this.callParent();
    },

    initEvents: function () {
        //make sure your window is rendered and have sizes and position
        if(!this.rendered) {
            this.on('afterrender', this.initEvents, this, {single: true});
            return;
        }

        this.mon(Ext.getBody(), 'click', this._checkCloseClick, this);
    }

    _checkCloseClick: function (event) {
        var cx = event.getX(), cy = event.getY(),
            box = this.getBox();

        if (cx < box.x || cx > box.x + box.width || cy < box.y || cy > box.y + box.height) {
            //clean up listener listener
            this.mun(Ext.getBody(), 'click', this._checkCloseClick, this);
            this.close();
        }
    }
}
maxmalov
  • 510
  • 2
  • 12
  • 3
    If you have a combobox in your window the dropdownlist can be rendered outside the windows boundaries. Resulting in unwanted closing of the window when you select an item outside of the windows boundaries. – VDP Mar 20 '13 at 11:50
  • after some modification it perfectly worked for me. thank you. – Umer Hayyat May 29 '17 at 08:38
2

You can try this also:

Ext.getBody().on('click', function(e, t){
    var el = win.getEl();

    if (!(el.dom === t || el.contains(t))) {
        win.close();
    }
});
nhahtdh
  • 55,989
  • 15
  • 126
  • 162
Aminesrine
  • 2,082
  • 6
  • 35
  • 64
0

I found adding a listener to the body and checking css classes felt a little hackey to me. You can actually override the private method _onMaskClick of Ext.ZIndexManager (see, completely not hackey). Which allows you to add your own configuration parameter (and even event) to all windows.

Ext.define('MyApp.ux.ZIndexManager_maskClick', {
  override: 'Ext.ZIndexManager',

  _onMaskClick: function ()
  {
    if (this.front)
    {
      var allowed = this.front.fireEvent('maskclick', this.front, this.mask);

      if (allowed !== false && this.front.closeOnMaskClick)
        this.front.close();
    }
    return this.callParent(arguments);
  },
});
Will S
  • 744
  • 8
  • 17