javascrpt控制父窗口关闭,子窗口也关闭(转)
B/S 系统的一个很常见的操作是,在主窗口中打开子窗口(例如单据窗口),在其中打开查找窗口,在查找窗口中打开类别选择子窗口,... 如此一层层下去,形成多级子窗口。然而,当退出 B/S 系统时,却只能一个个关闭这些窗口。
var __winRoot__ = top || parent || window; // 祖先窗口对象
var __winParent__ = __winRoot__; // 父窗口对象(默认为祖先窗口)
var __winTree__ = {subWinNames:''}; // 本窗口的子窗口对象集合。 subWinNames 记录所有子窗口的名称,方便遍历
//--------------------------------------------------------
window.closeSub = function()
{
__winTree_closeAllSubWins__(); // 关闭所有子窗口
__winTree_closeWin__(); // 关闭当前窗口
}
window.openSub = function(url, wname, property)
{
__winTree_openSubWin__(url, wname, property);
}
window.onbeforeunload = function()
{
var n = window.event.screenX - window.screenLeft;
var b = n > document.documentElement.scrollWidth-20;
if(b && window.event.clientY < 0 || window.event.altKey)
{
window.closeSub();
}
}
//--------------------------------------------------------
//////////////////////////////////////////////////////////
//
// 一些函数
//
//////////////////////////////////////////////////////////
//--------------------------------------------------------
// 指定窗口是否存在
//--------------------------------------------------------
function __winTree_isExistWin__(hdl){try{var ret=hdl && !hdl.closed}catch(e){var ret=false};return ret;}
//--------------------------------------------------------
//////////////////////////////////////////////////////////
//
// 窗口控制
//
//////////////////////////////////////////////////////////
//--------------------------------------------------------
// 构造窗口缺省名字
//--------------------------------------------------------
function __winTree_getDefaultWinName__()
{
return "__wn" + (new Date().getTime()) + "__"; // 用当前时间构造窗口缺省名字
}
//--------------------------------------------------------
// 打开子窗口,并添加到窗口目录树
//--------------------------------------------------------
function __winTree_openSubWin__(url, wname, property)
{
var hdl = window.open(url, wname, property);
__winTree_addSubWin__(wname, hdl); // 保存到子窗口对象集合
}
//--------------------------------------------------------
// 保存到子窗口对象集合
//--------------------------------------------------------
function __winTree_addSubWin__(subWinName, sWin)
{
var win = top ? top : window; // 获取本窗口的最上层窗口
var winTree = win.__winTree__;
winTree[subWinName] = sWin; // 将子窗口对象加入到集合中
winTree["subWinNames"] += subWinName + ","; // 所有子窗口名称集合
}
//--------------------------------------------------------
// 将指定窗口的子孙窗口对象,添加到指定窗口的父窗口中
//--------------------------------------------------------
// 使指定窗口的子孙窗口保持在目录树中的结构
// 否则指定窗口的子孙窗口将从目录树结构中断开,不能统一控制。
// (用于关闭指定窗口的操作时)
//--------------------------------------------------------
function __winTree_addSubWins2pWin__(thisWin)
{
thisWin = thisWin || window; // 缺省为本窗口
var pWin = thisWin.__winParent__;
var winTree = thisWin.__winTree__;
var arrSubWinNames = winTree.subWinNames.split(","); // 子窗口名字数组
var intSubWinNamesLen = arrSubWinNames.length;
for(var i=0; i<intSubWinNamesLen; i++)
{
var subWinName = arrSubWinNames[i]; // 指定窗口的子孙窗口名字
if (!subWinName) continue;
var sWin = winTree[subWinName]; // 指定窗口的子孙窗口对象
// 为避免和父窗口中已有的子窗口的名称相同,因此要加上缺省的、以当前时间来构造的名称
pWin.__winTree_addSubWin__(subWinName + __winTree_getDefaultWinName__(), sWin);
}
}
//--------------------------------------------------------
// 本窗口的所有下级子窗口执行指定动作
//--------------------------------------------------------
// funcName 要执行的函数名称(例如 close ,即 window.close() ,或者其他自己定义的函数,例如 changeBgColor 等等)
// argVals 要执行的函数的参数值
//--------------------------------------------------------
function __winTree_doWithSubs__(win, funcName, argVals)
{
if (!win || !funcName) return;
var winTree = win.__winTree__;
var arrSubWinNames = winTree.subWinNames.split(","); // 子窗口名字数组
var intSubWinNamesLen = arrSubWinNames.length;
for(var i=0; i<intSubWinNamesLen; i++)
{
var subWinName = arrSubWinNames[i]; // 子窗口名字
if (!subWinName) continue;
var sWin = winTree[subWinName]; // 子窗口对象
if (__winTree_isExistWin__(sWin))
{
sWin.__winTree_doWithSubs__(sWin, funcName, argVals); // 查找该子窗口的下级子窗口
sWin[funcName](argVals); // 执行指定的动作
}
}
}
//--------------------------------------------------------
// 初始化窗口目录树
//--------------------------------------------------------
function __winTree_init__()
{
if (__winTree_isExistWin__(opener)) // 如果存在父窗口
{
var pWin = opener.top; // 父窗口。有可能是在 iframe 中打开本窗体,因此父窗体应该是 opener 的顶级窗体
__winParent__ = pWin; // 祖先窗口
__winRoot__ = pWin;
var ppWin = pWin.opener;
if (__winTree_isExistWin__(ppWin)) // 修正祖先窗口
{
__winRoot__ = pWin.__winRoot__;
}
}
//alert([__winRoot__.document.title, __winParent__.document.title, window.document.title]); // for test only
}
//--------------------------------------------------------
// 关闭当前窗口
//--------------------------------------------------------
function __winTree_closeWin__(win)
{
win = win || window; // 缺省为关闭当前窗口
var pWin = win.__winParent__;
if (__winTree_isExistWin__(pWin)) // 如果指定窗口有父窗口,且未关闭
{
__winTree_addSubWins2pWin__(win); // 将指定窗口的子孙窗口对象,添加到指定窗口的父窗口中
}
win.opener = null; // 此语句用于取消“是否关闭此窗口”的提示
win.close(); // 关闭指定窗口
pWin.focus(); // 聚焦到父窗口
}
//--------------------------------------------------------
// 关闭本窗口的所有下级子窗口
//--------------------------------------------------------
function __winTree_closeAllSubWins__(win)
{
win = win || window; // 缺省为关闭当前窗口
__winTree_doWithSubs__(win, "close");
}
//--------------------------------------------------------
// 初始化
//--------------------------------------------------------
__winTree_init__();
这是因为,IE 并不提供窗口的级联结构控制,即不能一次性关闭所有子窗口(或者在所有子窗口中执行同一个函数)。这令人不满。
我写了一个函数库,可以完美解决这个问题,当关闭某个子窗口时,自动关闭其下的所有子窗口。当然,退出系统时,自动关闭所有子窗口。并且,可以在所有子窗口中执行指定的函数。实际上,后者是前者的基础,由于实现了后者的功能,前者就变成了后者的一个具体的应用。
但是有一个缺点就是在刷新主窗口的时候,功能失效,看看有没有高手,能通过写入cookie来解决或其它什么办法
var __winRoot__ = top || parent || window; // 祖先窗口对象
var __winParent__ = __winRoot__; // 父窗口对象(默认为祖先窗口)
var __winTree__ = {subWinNames:''}; // 本窗口的子窗口对象集合。 subWinNames 记录所有子窗口的名称,方便遍历
//--------------------------------------------------------
window.closeSub = function()
{
__winTree_closeAllSubWins__(); // 关闭所有子窗口
__winTree_closeWin__(); // 关闭当前窗口
}
window.openSub = function(url, wname, property)
{
__winTree_openSubWin__(url, wname, property);
}
window.onbeforeunload = function()
{
var n = window.event.screenX - window.screenLeft;
var b = n > document.documentElement.scrollWidth-20;
if(b && window.event.clientY < 0 || window.event.altKey)
{
window.closeSub();
}
}
//--------------------------------------------------------
//////////////////////////////////////////////////////////
//
// 一些函数
//
//////////////////////////////////////////////////////////
//--------------------------------------------------------
// 指定窗口是否存在
//--------------------------------------------------------
function __winTree_isExistWin__(hdl){try{var ret=hdl && !hdl.closed}catch(e){var ret=false};return ret;}
//--------------------------------------------------------
//////////////////////////////////////////////////////////
//
// 窗口控制
//
//////////////////////////////////////////////////////////
//--------------------------------------------------------
// 构造窗口缺省名字
//--------------------------------------------------------
function __winTree_getDefaultWinName__()
{
return "__wn" + (new Date().getTime()) + "__"; // 用当前时间构造窗口缺省名字
}
//--------------------------------------------------------
// 打开子窗口,并添加到窗口目录树
//--------------------------------------------------------
function __winTree_openSubWin__(url, wname, property)
{
var hdl = window.open(url, wname, property);
__winTree_addSubWin__(wname, hdl); // 保存到子窗口对象集合
}
//--------------------------------------------------------
// 保存到子窗口对象集合
//--------------------------------------------------------
function __winTree_addSubWin__(subWinName, sWin)
{
var win = top ? top : window; // 获取本窗口的最上层窗口
var winTree = win.__winTree__;
winTree[subWinName] = sWin; // 将子窗口对象加入到集合中
winTree["subWinNames"] += subWinName + ","; // 所有子窗口名称集合
}
//--------------------------------------------------------
// 将指定窗口的子孙窗口对象,添加到指定窗口的父窗口中
//--------------------------------------------------------
// 使指定窗口的子孙窗口保持在目录树中的结构
// 否则指定窗口的子孙窗口将从目录树结构中断开,不能统一控制。
// (用于关闭指定窗口的操作时)
//--------------------------------------------------------
function __winTree_addSubWins2pWin__(thisWin)
{
thisWin = thisWin || window; // 缺省为本窗口
var pWin = thisWin.__winParent__;
var winTree = thisWin.__winTree__;
var arrSubWinNames = winTree.subWinNames.split(","); // 子窗口名字数组
var intSubWinNamesLen = arrSubWinNames.length;
for(var i=0; i<intSubWinNamesLen; i++)
{
var subWinName = arrSubWinNames[i]; // 指定窗口的子孙窗口名字
if (!subWinName) continue;
var sWin = winTree[subWinName]; // 指定窗口的子孙窗口对象
// 为避免和父窗口中已有的子窗口的名称相同,因此要加上缺省的、以当前时间来构造的名称
pWin.__winTree_addSubWin__(subWinName + __winTree_getDefaultWinName__(), sWin);
}
}
//--------------------------------------------------------
// 本窗口的所有下级子窗口执行指定动作
//--------------------------------------------------------
// funcName 要执行的函数名称(例如 close ,即 window.close() ,或者其他自己定义的函数,例如 changeBgColor 等等)
// argVals 要执行的函数的参数值
//--------------------------------------------------------
function __winTree_doWithSubs__(win, funcName, argVals)
{
if (!win || !funcName) return;
var winTree = win.__winTree__;
var arrSubWinNames = winTree.subWinNames.split(","); // 子窗口名字数组
var intSubWinNamesLen = arrSubWinNames.length;
for(var i=0; i<intSubWinNamesLen; i++)
{
var subWinName = arrSubWinNames[i]; // 子窗口名字
if (!subWinName) continue;
var sWin = winTree[subWinName]; // 子窗口对象
if (__winTree_isExistWin__(sWin))
{
sWin.__winTree_doWithSubs__(sWin, funcName, argVals); // 查找该子窗口的下级子窗口
sWin[funcName](argVals); // 执行指定的动作
}
}
}
//--------------------------------------------------------
// 初始化窗口目录树
//--------------------------------------------------------
function __winTree_init__()
{
if (__winTree_isExistWin__(opener)) // 如果存在父窗口
{
var pWin = opener.top; // 父窗口。有可能是在 iframe 中打开本窗体,因此父窗体应该是 opener 的顶级窗体
__winParent__ = pWin; // 祖先窗口
__winRoot__ = pWin;
var ppWin = pWin.opener;
if (__winTree_isExistWin__(ppWin)) // 修正祖先窗口
{
__winRoot__ = pWin.__winRoot__;
}
}
//alert([__winRoot__.document.title, __winParent__.document.title, window.document.title]); // for test only
}
//--------------------------------------------------------
// 关闭当前窗口
//--------------------------------------------------------
function __winTree_closeWin__(win)
{
win = win || window; // 缺省为关闭当前窗口
var pWin = win.__winParent__;
if (__winTree_isExistWin__(pWin)) // 如果指定窗口有父窗口,且未关闭
{
__winTree_addSubWins2pWin__(win); // 将指定窗口的子孙窗口对象,添加到指定窗口的父窗口中
}
win.opener = null; // 此语句用于取消“是否关闭此窗口”的提示
win.close(); // 关闭指定窗口
pWin.focus(); // 聚焦到父窗口
}
//--------------------------------------------------------
// 关闭本窗口的所有下级子窗口
//--------------------------------------------------------
function __winTree_closeAllSubWins__(win)
{
win = win || window; // 缺省为关闭当前窗口
__winTree_doWithSubs__(win, "close");
}
//--------------------------------------------------------
// 初始化
//--------------------------------------------------------
__winTree_init__();
DEMO下载地址:https://files.cnblogs.com/ForFreeDom/父窗口关闭子窗口关闭.rar