从window.open返回一个值

时间:2014-09-10 22:07:10

标签: javascript google-chrome showmodaldialog

我们最近发现Chrome不再支持window.showModalDialog,这是有问题的,因为我们的企业应用程序使用此方法。

显然,有一个短期解决方法可以让你恢复showModalDialog,但它涉及修改注册表,这对我们普通用户来说太复杂(而且有风险)。因此,我不是这种解决方法的忠实粉丝。

长期解决方案显然是删除对这个过时方法的所有调用,并用方便的jQuery插件替换它们(例如VistaPrint的Skinny Modal Dialog plugin。顺便提一句其他建议。)

我们使用模态对话框的典型场景是在执行无法撤消的操作之前询问用户是/否确认,要求用户在继续之前同意条款和条件等。通常情况下onclick事件在模态对话框中的“是”或“确定”按钮如下所示:

window.returnValue = true;
window.close();

同样,“取消”或“否”按钮如下所示:

window.returnValue = false;
window.close();

我们可以从对话框中返回一个值非常方便,因为它允许“父”窗口被通知用户是否点击了“确定”或“取消”按钮,如下所示:

var options = "center:1;status:1;menubar:0;toolbar:0;dialogWidth:875px;dialogHeight:650px";
var termsOfServiceAccepted = window.showModalDialog(myUrl, null, options);
if (termsOfServiceAccepted) {
    ... proceed ...
}

我要提到的关于showModalDialog的最后一件事是,即使对话框中显示的文档来自不同的域,它也能很好地工作。让我们的javascript从http://the-client.com开始运行非常常见,但“服务条款”网页来自http://the-enterprise-vendor.com

我需要一个临时解决方案,我可以在我们处理长期解决方案时尽快部署。这是我的标准:

  • 现有JavaScript中的最小代码更改
  • 弹出窗口必须能够将值返回给“父”。通常这个值是布尔值,但它可以是任何简单类型(例如:string,int等)
  • 解决方案必须正常工作,即使内容的网址来自不同的域

这是我到目前为止所拥有的:

1)在我的JavaScript中添加以下方法:

function OpenDialog(url, width, height, callback)
{
    var win = window.open(url, "MyDialog", width, height, "menubar=0,toolbar=0");
    var timer = setInterval(function ()
    {
        if (win.closed)
        {
            clearInterval(timer);
            var returnValue = win.returnValue;
            callback(returnValue);
        }
    }, 500);
}

正如您在此方法中所看到的,我尝试通过隐藏菜单和工具栏使弹出窗口看起来与对话框类似,我每500毫秒设置一次以检查窗口是否已关闭由用户提供,如果是,请获取'returnValue'并调用回调。

2)用以下内容替换对showModalDialog的所有调用:

OpenDialog(myUrl, 875, 650, function (termsOfServiceAccepted)
{
    if (termsOfServiceAccepted)
    {
        ... proceed ....
    }
});

该方法的第四个参数是回调,我在此之前检查用户是否点击了“确定”按钮,然后才允许她继续。

我知道这是一个很长的问题,但基本上归结为:

  1. 您如何看待我提出的解决方案?
  2. 特别是,您认为我能够从使用window.open打开的窗口中获取returnValue吗?
  3. 您可以建议其他任何替代方案吗?

1 个答案:

答案 0 :(得分:15)

我有两个可以帮助你的想法,但第一个想法与CORS绑定,因此你将无法在不同的域中使用它,至少你可以访问这两个服务并配置它们。

第一个想法:

第一个与此native api有关。您可以在父窗口上创建一个像这样的全局函数:

window.callback = function (result) {
    //Code
}

正如您所看到的,它会收到一个 result 参数,该参数可以保存您需要的布尔值。您可以使用相同的旧 window.open(url)函数打开弹出窗口。弹出窗口的onlick事件处理程序可能如下所示:

function() {
    //Do whatever you want.
    window.opener.callback(true); //or false
}

第二个IDEA:解决问题

我得到的另一个想法是使用另一个native api在弹出窗口解析时触发父窗口上的事件(更好地称为跨文档消息传递)。所以你可以从父窗口执行此操作:

window.onmessage = function (e) {
    if (e.data) {
        //Code for true
    } else {
        //Code for false
    }
};

通过这种方式,您正在收听此窗口上的任何已发布消息,并检查附加到消息的数据是否为 true (用户在弹出窗口中单击“确定”)或 false < / em>(用户在弹出窗口中单击取消)。

在弹出窗口中,您应该向父窗口发布消息,在对应时附加 true false 值:

window.opener.postMessage(true, '*'); //or false

我认为这个解决方案完全符合您的需求。

修改 我写过,第二个解决方案也与CORS有关,但深入挖掘 我意识到跨文档消息传递与CORS无关