Javascript——等待用户交互而不冻结浏览器

Javascript -- wait for user interaction without freezing the browser

本文关键字:冻结 浏览器 交互 等待 用户 Javascript      更新时间:2023-09-26

我英语说得不太好。

我的公司为ie开发了一个web应用程序,它非常努力地使用了showModalDialog函数并等待结果。

我们计划将应用程序的使用扩展到其他浏览器(Firefox, Chrome),我需要将"showModalDialog逻辑"替换为在所有浏览器上都能正常工作的逻辑。

我最初尝试使用ajaxcontroltoolkit modalpopupiframe里面。

我的问题是,在我显示modalpopup之后,我不能等待用户关闭弹出窗口而不冻结web界面。

function OpenDialog() {
    var result = window.showModalDialog("page1.html", "input_parameter", "width:100px; height:100px");
    //When the popup went closed
    alert("result: " + result);
}
//Override showModalDialog function for compatibility with other browser
function myShowModalDialog(url, pars, options) {
    //show a jquery modalpopup or ajaxcontroltoolkit modalpopup with an iframe ....
    iframe.src = url;
    //I need to wait here until the modal popup closed
    //HOW?
    //get the value from popup
    var res = ???????;
    return res;
}
window.showModalDialog = myShowModalDialog;

我不能更改web应用中每个页面的逻辑。

我寻找一种方法来覆盖showModalDialog函数并重新创建相同的逻辑(等待直到弹出窗口关闭并获得弹出窗口为调用者提供的结果)。

任何想法?感谢所有

您已经发现了JavaScript严重依赖异步性、事件处理程序和回调函数的原因。

最好的解决方案是重构你的代码,让你的事件触发事件处理程序,使用jQuery或类似的东西将事件处理程序绑定到事件。或者,您总是可以在超时循环中使用函数来定期检查模态是否已关闭,并在关闭时执行代码的延续。不过,这是相当粗糙的,我不建议这样做。一般来说,试图强迫异步代码适应同步模型会变得非常混乱。

除非我没听懂,否则你需要的是用户关闭对话框时的回调,对吧?

无论用户关闭对话框时执行什么方法,都要对其进行修补以调用您的函数。(monkey patch是指为现有代码添加功能,但同时保留旧代码的代码)

所以如果你的close方法/函数看起来像:

myCloseDialog = function(){
  // do important closing stuff
}

然后你可以像这样做:

myNewCloseDialog = function(){
  // do important callback stuff, or call your callback function
  myCloseDialog(arguments);
}

顺便说一下,你的英语很好。

我在评论中创建了一个简短的示例:

<!DOCTYPE html>
<html>
  <head>
    <title>modal overlay</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
      .overlay
      {
        background-color: rgba(0, 0, 0, 0.1);
        position:absolute;
        top:0;
        left:0;
        width:100%;
        height:100%;
        z-index: 100;
        margin:0;
        display:none;
      }
      .box
      {
        position:absolute;
        top:0;
        left:0;
        bottom:0;
        right:0;
        width:400px;
        height:300px;
        background:white;
        margin:auto;
        padding:10px;
      }
    </style>
    <!--
      prepare a style to show/hide overlay and
      prevent lost focus when clicking outside the box
    -->
    <template id="template1">
      <style id="style-modal">
        *
        { pointer-events: none;
        }
        .overlay *
        {pointer-events: auto;
        }
        .overlay
        { display:block!important;
        }
      </style>
    </template>
  </head>
  <body>
    <input id="some-input1" type="text">
    <button class="modal-open" type="button">open modal dialog</button>
    <div id="overlay1" class="overlay">
      <div class="box">
        <input id="modal-input1" type="text">
        <button type="button" class="modal-close">close</button>
      </div>
    </div>
    <script>
      document.addEventListener
      ( 'DOMContentLoaded',
        function(ev)
        {
          var
            template1  = document.getElementById('template1'),
            styleModal = template1.content.getElementById('style-modal'),
            overlay1   = document.getElementById('overlay1'),
            box        = overlay1.querySelector('.box'),
            head       = document.querySelector('head')
          ;
          //TODO: could iterate over querySelectorAll
          document.querySelector('button.modal-open').addEventListener
          ( 'click',
            function(ev) { head.appendChild(styleModal); },
            false
          )
          overlay1.querySelector('button.modal-close').addEventListener
          ( 'click',
            function(ev)
            { template1.content.appendChild(styleModal);
              document.dispatchEvent(new CustomEvent('closemodal', {detail:{relatedTarget:box}}));
            },
            false
          )
        },
        false
      );
      document.addEventListener
      ( 'closemodal',
        function(ev){ alert(ev.detail.relatedTarget.querySelector('input').value); },
        false
      );
    </script>
  </body>
</html>

注意这个例子使用了<template>元素,它还没有被IE实现。您可以轻松地在脚本中生成style-元素,将其保存在一个变量中,并将其添加到/从头部移除。

看看我的showModalDialog多边形使用模态元素和ECMAScript 6生成器,所以它不需要一个显式的回调函数。showModalDialog()之后的语句将在关闭模态后运行。