点击遮罩层时如何关闭 ExtJS 模态窗口?

13

如果我创建了一个模态窗口:

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

如何知道用户何时单击窗口外的遮罩?在Sencha Touch中,有一个hideOnMaskTap的配置项可以让我指定。在extJS中,有什么事件/配置项可以实现这个功能呢?


一个加载遮罩没有点击事件。 - Johan Haest
4个回答

18

Tramway的情况(有点)适用于模态或非模态窗口。但是,如果像组合框的boundlist那样的子组件浮动在窗口边界外,则不适用。

然而,如果您仍然使用模态窗口,则可以像这样监听遮罩上的单击事件。

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' });
    }
});

1
这是正确答案,使用委托非常聪明。窗口必须是模态的,否则当用户与其他窗口交互时,它关闭会很奇怪。模态窗口有视觉提示,向用户表明这一点。 - jjrv
1
initComponent 函数的第一行不应该是 var me = this; 吗? - Geo
好的解决方案,只有一件事情需要注意 - 你应该扩展Ext.window.Window,而不仅仅是基本容器,否则你将会缺少来自Panel和Window类的所有内容: extend: 'Ext.window.Window', - Mike Demenok
如果您有一个没有模态的窗口,那么您不能使用 'x-mask'。这是什么提示? - John Paul Cárdenas
就像jjrv所说:“窗口无论如何都必须是模态的,因为否则当用户与另一个窗口交互时关闭它会很奇怪。模态窗口具有视觉提示以向用户建议此操作。” 为什么你不想把它设置为模态?如果你真的不想看到遮罩,只需将其不透明度设置为0即可。 - VDP
非常好的答案。我特别喜欢使用 mon 的方式。 - MarthyM

11

您可以监听所有的点击事件,然后检查点击位置是否超出了窗口。

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();
        }
    }
}

3
如果您的窗口中有一个组合框,则下拉列表可能会呈现在窗口边界之外,导致在选择窗口边界之外的项目时意外关闭窗口。 - VDP
经过一些修改,它完美地为我工作了。谢谢。 - Umer Hayyat

2
你也可以尝试这个:
Ext.getBody().on('click', function(e, t){
    var el = win.getEl();

    if (!(el.dom === t || el.contains(t))) {
        win.close();
    }
});

1
我喜欢这个想法!在我的情况下,我使用没有边框的窗口等。因此,这可以帮助我在必须隐藏时将其隐藏 :) - Andron
未捕获的引用错误:win未定义。 - Geo

0

我发现给 body 添加监听器并检查 css 类对我来说有点 hackey。实际上,您可以覆盖 Ext.ZIndexManager 的私有方法 _onMaskClick(完全不是 hackey)。这允许您向所有窗口添加自己的配置参数(甚至事件)。

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);
  },
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接