如,有如下窗体
var formWin = new Ext.Window({ ??? title: 'new window' ??? ,width: 200 ??? ,height: 400 ??? ,html: 'This will be always on top' }); 现要使得这个窗体总是在其他窗体的前面,而且不影响其他窗体的使用(使用modal:true 选项可创建模态窗,但会冻结整个屏幕)。 国际惯例,先在 搜索一下,最快捷、准确的方法是。果然google没让人失望,{dy}页里就找到了。 他介绍的方法是修改Ext.WindowGroup 类(位于 widgets/WindowManager.js )的私有方法sortWindows(),改为: ??? var sortWindows = function(d1, d2){ ??????? return (!d1.alwaysOnTop && (d2.alwaysOnTop || !d1._lastAccess || d1._lastAccess < d2._lastAccess)) ? -1 : 1; ??? }; 这样就运行在初始化window时可以使用一个新的选项:alwaysOnTop ,如: var formWin = new Ext.Window({ ??? title: 'new window' ??? ,width: 200 ??? ,height: 400 ??? ,html: 'This will be always on top' ??? ,alwaysOnTop: true }); 修改做的修改很少,但要hack源码肯定是最差的备选的方案。 而sortWindows 是个私有方法,js是无法从类外覆盖私有方法的,具体可参考 因此尝试剑走偏锋,看看有没其他方案。查看 ,在中的部分发现有两个事件是相关的: activate : ( Ext.Window this ) Fires after the window has been visually activated via setActive. deactivate : ( Ext.Window this ) Fires after the window has been visually deactivated via setActive. 一般来说,要使窗体总在最前方,应该是先触发了deactivate事件,因此在这时再主动设置为active,则可使窗体总保持xx状态也即是最前方了。 尝试如下: formWin.on('deactivate', function(){ ??? this.setActive(true); }) 发现无效。阅读setActive的源码后知道原来setActive 只是用来设置是否显示窗体阴影是否显示。 Ext.Window 还有一个公共方法可以利用: toFront() : Ext.Window Brings this window to the front of any other visible windows 尝试用来代替setActive: formWin.on('deactivate', function(){ ??? this.toFront(); }) 发现也无效,查看源码发现Ext.Window.toFront() 实际是调用 Ext.WindowGroup.bringToFront(win),而在 Ext.WindowGroup.bringToFront(win) 里会判断 win 是否是当前窗口,如果是就不做任何操作,而在deactivate 里,当前窗口正是formWin,所以不会对他做任何操作。 在仔细跟读源码,原来决定窗体哪个在前面,是使用Ext.Window.setZIndex() 在设置窗体z轴(垂直于电脑屏幕的轴)的值,越高的则越前。 知道底层实现原理就好办了,只要给formWin设置一个较大的zIndex值则可,尝试如: formWin.on('deactivate', function(){ ??? this.setZIndex(9999); }) 点击其他窗体,formWin总是显示在最前方了。 但窗体的数量是不确定的,而Ext用来调整各个窗体的前后顺序是动态的,具体实现源码为: ??? // private ??? var orderWindows = function(){ ??????? var a = accessList, len = a.length; ??????? if(len > 0){ ??????????? a.sort(sortWindows); ??????????? var seed = a[0].manager.zseed; ??????????? for(var i = 0; i < len; i++){ ??????????????? var win = a[i]; ??????????????? if(win && !win.hidden){ ??????????????????? win.setZIndex(seed + (i*10)); ??????????????? } ??????????? } ??????? } ??????? activateLast(); ??? }; 因此,也要根据当前窗体的数量来动态调整zIndex的值,代码改为: formWin.on('deactivate', function(){ ??? var i=1; ??? this.manager.each(function(){i++}); ??? this.setZIndex(this.manager.zseed + (i*10)); }) 至此,可以说是已经完整实现了需求。 但有时窗体是直接new出来,没有赋值给临时变量,需要能在构造函数中设置。幸好Ext的接口丰富,有提供一个plugin的选项来提供扩展(如何写一个Ext的plugin: ),最终实现代码为: var formWin = new Ext.Window({ ??? title: 'new window' ??? ,width: 200 ??? ,height: 400 ??? ,html: 'This will be alwasy on top' ??? ,plugins: new function(){ ??????? this.init = function(win){ ???????????? win.on('deactivate', function(){ ??????????????????? var i=1; ??????????????????? this.manager.each(function(){i++}); ??????????????????? this.setZIndex(this.manager.zseed + (i*10)); ??????????????? }) ??????? } ??? } }); 如果要实现重用,{zh0}把plugin实现代码抽取为一个独立的plugin,如: Ext.ux.WindowAlwaysOnTop = function(){ ??? this.init = function(win){ ???????? win.on('deactivate', function(){ ??????????? var i=1; ??????????? this.manager.each(function(){i++}); ??????????? this.setZIndex(this.manager.zseed + (i*10)); ???????? }) ??? } } 以后使用则很方便了: var formWin = new Ext.Window({ ??? title: 'new window' ??? ,width: 200 ??? ,height: 400 ??? ,html: 'This will be always on top' ??? ,plugin: new Ext.ux.WindowAlwaysOnTop }); 效果如图 |
转自: