如何在chrome 37中使window.showmodaldialog工作?

时间:2014-09-04 10:25:09

标签: javascript jquery asp.net google-chrome cross-browser

我们有一个巨大的网络应用程序,我们使用window.showmodaldialog进行警报,确认和弹出窗口。自Chrome版本37起,此呼叫已被禁用。

是否有任何快速解决方法可以让window.showmodaldialog在最新版本的Chrome中运行?

我在这里添加了window.showmodaldialog的解决方法,虽然这不是一个完美的解决方法,因为这不会像showmodaldialog那样破坏代码执行,而是会打开弹出窗口。

window.showModalDialog = function (url, arg, feature) {
        var opFeature = feature.split(";");
       var featuresArray = new Array()
        if (document.all) {
           for (var i = 0; i < opFeature.length - 1; i++) {
                var f = opFeature[i].split("=");
               featuresArray[f[0]] = f[1];
            }
       }
        else {

            for (var i = 0; i < opFeature.length - 1; i++) {
                var f = opFeature[i].split(":");
               featuresArray[f[0].toString().trim().toLowerCase()] = f[1].toString().trim();
            }
       }



       var h = "200px", w = "400px", l = "100px", t = "100px", r = "yes", c = "yes", s = "no";
       if (featuresArray["dialogheight"]) h = featuresArray["dialogheight"];
        if (featuresArray["dialogwidth"]) w = featuresArray["dialogwidth"];
       if (featuresArray["dialogleft"]) l = featuresArray["dialogleft"];
        if (featuresArray["dialogtop"]) t = featuresArray["dialogtop"];
        if (featuresArray["resizable"]) r = featuresArray["resizable"];
       if (featuresArray["center"]) c = featuresArray["center"];
      if (featuresArray["status"]) s = featuresArray["status"];
        var modelFeature = "height = " + h + ",width = " + w + ",left=" + l + ",top=" + t + ",model=yes,alwaysRaised=yes" + ",resizable= " + r + ",celter=" + c + ",status=" + s;

        var model = window.open(url, "", modelFeature, null);

       model.dialogArguments = arg;

    }

只需将此代码放在页面的首部。

11 个答案:

答案 0 :(得分:34)

我在页眉中添加了以下javascript,似乎可以正常工作。它检测浏览器何时不支持showModalDialog并附加使用window.open的自定义方法,解析对话框规格(高度,宽度,滚动等),以开启器为中心并将焦点设置回窗口(如果焦点丢失)。此外,它使用URL作为窗口名称,以便每次都不会打开新窗口。如果您将窗口args传递给模态,则需要编写一些额外的代码来修复它。弹出窗口不是模态的,但至少你不需要改变很多代码。可能需要为你的情况做一些工作。

<script type="text/javascript">
  // fix for deprecated method in Chrome 37
  if (!window.showModalDialog) {
     window.showModalDialog = function (arg1, arg2, arg3) {

        var w;
        var h;
        var resizable = "no";
        var scroll = "no";
        var status = "no";

        // get the modal specs
        var mdattrs = arg3.split(";");
        for (i = 0; i < mdattrs.length; i++) {
           var mdattr = mdattrs[i].split(":");

           var n = mdattr[0];
           var v = mdattr[1];
           if (n) { n = n.trim().toLowerCase(); }
           if (v) { v = v.trim().toLowerCase(); }

           if (n == "dialogheight") {
              h = v.replace("px", "");
           } else if (n == "dialogwidth") {
              w = v.replace("px", "");
           } else if (n == "resizable") {
              resizable = v;
           } else if (n == "scroll") {
              scroll = v;
           } else if (n == "status") {
              status = v;
           }
        }

        var left = window.screenX + (window.outerWidth / 2) - (w / 2);
        var top = window.screenY + (window.outerHeight / 2) - (h / 2);
        var targetWin = window.open(arg1, arg1, 'toolbar=no, location=no, directories=no, status=' + status + ', menubar=no, scrollbars=' + scroll + ', resizable=' + resizable + ', copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
        targetWin.focus();
     };
  }
</script>

答案 1 :(得分:15)

来自http://codecorner.galanter.net/2014/09/02/reenable-showmodaldialog-in-chrome/

它被设计弃用了。您可以重新启用showModalDialog支持,但只能暂时启用 - 直到2015年5月。使用这段时间创建替代解决方案。

以下是在Chrome for Windows中的操作方法。打开注册表编辑器(regedit)并创建以下密钥:

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Chrome\EnableDeprecatedWebPlatformFeatures

EnableDeprecatedWebPlatformFeatures项下创建一个名称为1且值为ShowModalDialog_EffectiveUntil20150430的字符串值。要验证是否已启用该策略,请访问chrome:// policy URL。

<小时/> 更新: 如果上述内容对你不起作用,这是另一种尝试方法。

  1. http://www.chromium.org/administrators/policy-templates
  2. 下载Chrome ADM模板
  3. 提取并导入与您的语言区域相关的策略(例如,windows \ adm \ en-US \ chrome.adm。您可以通过gpedit.msc或在Windows的Home版本上使用这些实用程序导入:http://blogs.technet.com/b/fdcc/archive/2008/05/07/lgpo-utilities.aspx
  4. 在“管理模板”下,找到Google Chrome模板并启用“启用弃用的Web平台Feautes”。
  5. 打开此功能并添加“ShowModalDialog_EffectiveUntil20150430”键。

答案 2 :(得分:5)

这篇文章(Why is window.showModalDialog deprecated? What to use instead?)似乎暗示showModalDialog已被弃用。

答案 3 :(得分:3)

这里提供了一个非常好的,有效的JavaScript解决方案: https://github.com/niutech/showModalDialog

我个人使用它,像以前一样用于其他浏览器,并为chrome浏览器创建一个新对话框。

以下是如何使用它的示例:

function handleReturnValue(returnValue) {
    if (returnValue !== undefined) {
        // do what you want
    }
}

var myCallback = function (returnValue) { // callback for chrome usage
    handleReturnValue(returnValue);
};

var returnValue = window.showModalDialog('someUrl', 'someDialogTitle', 'someDialogParams', myCallback); 
handleReturnValue(returnValue); // for other browsers except Chrome

答案 4 :(得分:1)

我不会尝试暂时启用已弃用的功能。根据{{​​3}}的MDN文档,已经有了填充showModalDialog

我刚刚使用它将windows.showModalDialog作为用户脚本添加到旧版企业应用程序中,但如果您有权访问源代码,您显然也可以将其添加到HTML的头部。

答案 5 :(得分:1)

答案 6 :(得分:1)

创建跨浏览器ModalDialog

function _showModalDialog(url, width, height, closeCallback) {
    var modalDiv,
        dialogPrefix = window.showModalDialog ? 'dialog' : '',
        unit = 'px',
        maximized = width === true || height === true,
        w = width || 600,
        h = height || 500,
        border = 5,
        taskbar = 40, // windows taskbar
        header = 20,
        x,
        y;

    if (maximized) {
        x = 0;
        y = 0;
        w = screen.width;
        h = screen.height;
    } else {
        x = window.screenX + (screen.width / 2) - (w / 2) - (border * 2);
        y = window.screenY + (screen.height / 2) - (h / 2) - taskbar - border;
    }

    var features = [
            'toolbar=no',
            'location=no',
            'directories=no',
            'status=no',
            'menubar=no',
            'scrollbars=no',
            'resizable=no',
            'copyhistory=no',
            'center=yes',
            dialogPrefix + 'width=' + w + unit,
            dialogPrefix + 'height=' + h + unit,
            dialogPrefix + 'top=' + y + unit,
            dialogPrefix + 'left=' + x + unit
        ],
        showModal = function (context) {
            if (context) {
                modalDiv = context.document.createElement('div');
                modalDiv.style.cssText = 'top:0;right:0;bottom:0;left:0;position:absolute;z-index:50000;';
                modalDiv.onclick = function () {
                    if (context.focus) {
                        context.focus();
                    }
                    return false;
                }
                window.top.document.body.appendChild(modalDiv);
            }
        },
        removeModal = function () {
            if (modalDiv) {
                modalDiv.onclick = null;
                modalDiv.parentNode.removeChild(modalDiv);
                modalDiv = null;
            }
        };

    // IE
    if (window.showModalDialog) {
        window.showModalDialog(url, null, features.join(';') + ';');

        if (closeCallback) {
            closeCallback();
        }
    // Other browsers
    } else {
        var win = window.open(url, '', features.join(','));
        if (maximized) {
            win.moveTo(0, 0);
        }

        // When charging the window.
        var onLoadFn = function () {
                showModal(this);
            },
            // When you close the window.
            unLoadFn = function () {
                window.clearInterval(interval);
                if (closeCallback) {
                    closeCallback();
                }
                removeModal();
            },
            // When you refresh the context that caught the window.
            beforeUnloadAndCloseFn = function () {
                try {
                    unLoadFn();
                }
                finally {
                    win.close();
                }
            };

        if (win) {
            // Create a task to check if the window was closed.
            var interval = window.setInterval(function () {
                try {
                    if (win == null || win.closed) {
                        unLoadFn();
                    }
                } catch (e) { }
            }, 500);

            if (win.addEventListener) {
                win.addEventListener('load', onLoadFn, false);
            } else {
                win.attachEvent('load', onLoadFn);
            }

            window.addEventListener('beforeunload', beforeUnloadAndCloseFn, false);
        }
    }
}

答案 7 :(得分:1)

    (function() {
        window.spawn = window.spawn || function(gen) {
            function continuer(verb, arg) {
                var result;
                try {
                    result = generator[verb](arg);
                } catch (err) {
                    return Promise.reject(err);
                }
                if (result.done) {
                    return result.value;
                } else {
                    return Promise.resolve(result.value).then(onFulfilled, onRejected);
                }
            }
            var generator = gen();
            var onFulfilled = continuer.bind(continuer, 'next');
            var onRejected = continuer.bind(continuer, 'throw');
            return onFulfilled();
        };
        window.showModalDialog = window.showModalDialog || function(url, arg, opt) {
            url = url || ''; //URL of a dialog
            arg = arg || null; //arguments to a dialog
            opt = opt || 'dialogWidth:300px;dialogHeight:200px'; //options: dialogTop;dialogLeft;dialogWidth;dialogHeight or CSS styles
            var caller = showModalDialog.caller.toString();
            var dialog = document.body.appendChild(document.createElement('dialog'));
            dialog.setAttribute('style', opt.replace(/dialog/gi, ''));
            dialog.innerHTML = '<a href="#" id="dialog-close" style="position: absolute; top: 0; right: 4px; font-size: 20px; color: #000; text-decoration: none; outline: none;">&times;</a><iframe id="dialog-body" src="' + url + '" style="border: 0; width: 100%; height: 100%;"></iframe>';
            document.getElementById('dialog-body').contentWindow.dialogArguments = arg;
            document.getElementById('dialog-close').addEventListener('click', function(e) {
                e.preventDefault();
                dialog.close();
            });
            dialog.showModal();
            //if using yield
            if(caller.indexOf('yield') >= 0) {
                return new Promise(function(resolve, reject) {
                    dialog.addEventListener('close', function() {
                        var returnValue = document.getElementById('dialog-body').contentWindow.returnValue;
                        document.body.removeChild(dialog);
                        resolve(returnValue);
                    });
                });
            }
            //if using eval
            var isNext = false;
            var nextStmts = caller.split('\n').filter(function(stmt) {
                if(isNext || stmt.indexOf('showModalDialog(') >= 0)
                    return isNext = true;
                return false;
            });
            dialog.addEventListener('close', function() {
                var returnValue = document.getElementById('dialog-body').contentWindow.returnValue;
                document.body.removeChild(dialog);
                nextStmts[0] = nextStmts[0].replace(/(window\.)?showModalDialog\(.*\)/g, JSON.stringify(returnValue));
                eval('{\n' + nextStmts.join('\n'));
            });
            throw 'Execution stopped until showModalDialog is closed';
        };
    })()

;

**Explanation:
------------**
The best way to deal with showModalDialog for older application conversions is use to `https://github.com/niutech/showModalDialog` inorder to work with show modal dialogs  and if modal dailog has ajax calls you need to create object and set the parameters of function to object and pass below...before that check for browser and set the useragent...example: agentStr = navigator.userAgent; and then check for chrome

var objAcceptReject={}; // create empty object and set the parameters to object and send to the other functions as dialog when opened in chrome breaks the functionality
    function rejectClick(index, transferId) {
        objAcceptReject.index=index;
        objAcceptReject.transferId=transferId;

     agentStr = navigator.userAgent;

                var msie = ua.indexOf("MSIE ");

                if (msie > 0) // If Internet Explorer, return version number
                {
                    var ret = window.showModalDialog("/abc.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");   

                    if (ret=="true") {
                        doSomeClick(index);
                    }

                } else if ((agentStr.indexOf("Chrome")) >- 1){
                spawn(function() {

                    var ret = window.showModalDialog("/abcd.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");   

                    if (ret=="true") {// create an object and store values in objects and send as parameters
                        doSomeClick(objAcceptReject.index);
                    }

                });

                }
                else {
                    var ret = window.showModalDialog("/xtz.jsp?accept=false",window,"dialogHeight:175px;dialogWidth:475px;scroll:no;status:no;help:no");   

                    if (ret=="true") {
                        doSomeClick(index);
                    }
                }

答案 8 :(得分:1)

使用window.open()打开窗口时,window.returnValue属性不能直接使用,而使用window.showModalDialog()时,window.returnValue属性可以使用

因此,在您的情况下,您有两种选择可以实现您想要的目标。

选项1-使用window.showModalDialog()

在您的父页面

var answer = window.showModalDialog(<your page and other arguments>)
if (answer == 1)
 { do some thing with answer }

在子页面中,您可以直接使用window.returnValue之类的

window.returnValue = 'value that you want to return';

showModalDialog 暂停执行JavaScript,直到关闭对话框,并且在关闭对话框时可以从打开的对话框中获取返回值。但是showModalDialog的问题在于它是许多现代浏览器均不支持。相反,window.open只是异步打开一个窗口(用户可以访问父窗口和打开的窗口)。并且JavaScript执行将立即继续。这使我们进入了选项2

选项2-使用window.open() 在您的父页面中,编写一个用于打开对话框的函数。

function openDialog(url, width, height, callback){
if(window.showModalDialog){
    options = 'dialogHeight: '+ height + '; dialogWidth: '+ width + '; scroll=no'
    var returnValue = window.showModalDialog(url,this,options);
    callback(returnValue)
}
else {
    options ='toolbar=no, directories=no, location=no, status=yes, menubar=no, resizable=yes, scrollbars=no, width=' + width + ', height=' + height; 
        var childWindow = window.open(url,"",options);
        $(childWindow).on('unload',function(){
            if (childWindow.isOpened == null) {
                childWindow.isOpened = 1;
            }
            else {
                if(callback){
                    callback(childWindow.returnValue);
                }
            }
        });
}

}

并且每当您要使用时,打开一个对话框。编写一个处理返回值的回调并将其作为参数传递给openDialog函数

function callback(returnValue){
if(returnValue){
    do something nice with the returnValue
}}

调用函数

openDialog(<your page>, 'width px', 'height px', callbak);

查看有关如何replace window.showModalDialog with window.open

的文章

答案 9 :(得分:0)

  

不推荐使用window.showModalDialog(意图删除:   window.showModalDialog(),从Web中删除showModalDialog   平台)。 [...]最新的计划是移除showModalDialog   在Chromium 37.这意味着该功能将在Opera 24和   Chrome 37,两者都应该在九月发布。[...]

答案 10 :(得分:0)

是的,已被弃用。花了昨天重写代码,改为使用Window.open和PostMessage。