在将应用程序从 Windows 迁移到 Web 平台时,经常会遇到一些仅在 Windows Form 中可用的功能需要在 Web 形式中实现。例如,关闭子窗口的功能。虽然这听起来简单,但在 Web 环境中实现起来可能会比预期的要复杂一些。
本文的目标是实现一个面向对象的客户端解决方案,以便在 Web 应用中关闭子窗口。通过一些研究,发现调用 window.open
会返回一个 window
对象,之后可以在任何时候调用其 close
方法。问题在于如何存储每个打开的窗口对象,以及如何检测浏览器关闭以关闭子窗口。
请注意,JavaScript中创建对象的详细讨论超出了本文的范围。
首先,需要持久化由 window.open
函数调用返回的窗口对象。通过将这些对象存储在一个私有数组中来实现这一点。
function windowController() {
var loadedWindows = new Array();
// ...
}
在JavaScript中,对象声明类似于函数声明。
现在,需要一个公共方法来包装 window.open
函数,以便捕获返回的对象并将其添加到数组中。
this.popUpWindow = function(wndUrl, wndName, wndWidth, wndHeight) {
var windObj = null;
try {
if (typeof wndWidth == 'undefined') wndWidth = 500;
if (typeof wndHeight == 'undefined') wndHeight = 250;
windObj = window.open(wndUrl, wndName, 'toolbar=0,menubar=0,resizable=0,location=0,directories=0,width=' + wndWidth + ',height=' + wndHeight);
windObj.registerID = wndName;
loadedWindows[loadedWindows.length] = windObj;
} catch (ex) {
alert('WindowController.popUpWindow: Exception occured, message: ' + ex.message);
}
return windObj;
}
由于正在包装 window.open
,决定只允许每个句柄 ID 打开一个实例,通过检查 ID 与已经加载的每个窗口句柄,如果存在,则简单地调用 focus
(这类似于 Windows Forms 中的预期行为)。
this.popUpWindow = function(wndUrl, wndName, wndWidth, wndHeight) {
var windObj = null;
try {
windObj = findWindow(wndName);
if (windObj != null) {
windObj.focus();
} else {
// ...
}
} catch (ex) {
alert('WindowController.popUpWindow: Exception occured, message: ' + ex.message);
}
return windObj;
}
function findWindow(winHandle) {
for (var i = 0; i < loadedWindows.length; i++) {
if (loadedWindows[i].closed == true) {
loadedWindows.splice(i, 1);
i--;
} else {
if (loadedWindows[i].registerID == winHandle) return loadedWindows[i];
}
}
return null;
}
最后,需要一种方法来知道浏览器何时关闭,以便关闭所有子窗口。当然,与其他浏览器相比,IE 有不同的方式注册事件,所以创建了一个通用方法来实现这一点。
function WireEvent(elem, target, func) {
if (elem.addEventListener) elem.addEventListener(target, func, false);
else if (elem.attachEvent) elem.attachEvent(target, func);
}
WireEvent(window, 'onunload', _windowController.closeAllWindows);
其中 onunload
函数处理如下:
this.closeAllWindows = function() {
for (var x = 0; x < loadedWindows.length; x++) {
try {
loadedWindows[x].close();
} catch (err) {
alert('WindowController.closeAllWindows: Exception occured, message: ' + err.message);
}
}
}
看起来一切都准备就绪了,最后需要能够初始化对象,以便可以从代码中访问它,所以在 js 文件的顶部添加了调用,如下所示:
var _windowController = new windowController();
_windowController.popUpWindow('ChildForm.aspx', 'ChildForm');