如何故意冻结浏览器窗口(如警报,确认和提示)?

时间:2019-05-01 21:27:42

标签: javascript browser window freeze synchronous

有没有办法像alertconfirmprompt(简称:“ acp”)那样冻结浏览器窗口?

我想显示一个带有自定义css的模式对话框,而不是“ acp”的本机弹出窗口,但是我希望能够冻结浏览器,直到我得到用户的反馈,就像“ acp”一样。

可是,为什么呢?这是不好的做法(嗯,我得投票)!
因此,当这是一种不好的做法时-为什么“ acp”实际上提供了这种同步行为? 因为在某些特定情况下,它恰恰是合适的UX的正确工具。那些本机模式看起来确实很丑陋,同时也非常有限。

这只是一个简单而又肮脏的示例,在此示例中,冻结浏览器直到用户提供反馈是完全可以的。假设我们有一个form和一个input type="reset"元素。因此,在我们真正让form重置之前,我们会询问用户类似的信息:“确定要重置(数据将丢失)吗?”。

如果我对本机模态外观没问题(不是),我可以这样做:

var handleSubmit = function( e ) {
  confirm('Are you sure you want to reset (data will be lost)?') || e.preventDefault()
}
$('form').on( 'reset', handleSubmit ) // just using jQuery here for the sake of shortness
// Edit to make Herohtar hopefully feel much better:
// using jQuery here for the sake of lazyness :)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
  <input placeholder="type something, reset and cancel to keep input value" style="width:100%">
  <input type="reset">
</form>

所以“每个人”都应该同意(编辑:或者至少有人可以),这不是坏习惯,对吗?
但是如何通过自定义样式的modal / dialog / popup实现相同的功能?
我当然不是在要求HTML / CSS部分,而是要求能够通过JavaScript冻结浏览器窗口!

说实话,我实际上希望对此表示歉意,但也许有一个 Killer JavaScript Ninja ,他有一个特殊的技巧可以实现...


注意:我确切地知道最终如何获得相同的结果,但是我正在寻找一种实际的冻结/同步功能,以使代码简单明了,减少黑客攻击。

2 个答案:

答案 0 :(得分:2)

您可以将除弹出框外的所有内容都放在div中。然后,您可以通过CSS打开/关闭指针事件。

div中的所有内容都将不再是可交互的。这样会冻结浏览器窗口。

.freeze { pointer-events: none; }

注意::将pointer-events添加到元素时,这也会影响所有子元素,因此将其放置在主体上也会锁定弹出窗口。

关闭弹出窗口后,我们可以从div中删除freeze类,一切将再次开始工作。

const content = document.getElementById('content')
const overlay = document.querySelector('.overlay')
const a = document.querySelector('.open-overlay')
const close = document.querySelector('.overlay .close')

// Open a popup and freeze the browser content
a.addEventListener('click', e => {
  e.preventDefault()
  content.classList.add('freeze')
  overlay.classList.remove('hidden')
})

// Close the popup window and unfreeze the browser content
close.addEventListener('click', e => {
  e.preventDefault()
  content.classList.remove('freeze')
  overlay.classList.add('hidden')
})
.freeze { pointer-events: none; }

.hidden { display: none; }

.overlay {
  position: fixed;
  z-index: 100;
  padding: 20px;
  background: white;
  border: solid 1px #ccc;
  width: 300px;
  top: 20px;
  left: 0;
  right: 0;
  margin: auto;
}
<div class="overlay hidden">
  <h1>Overlay</h1>
  <a href="" class="close">Close</a>
</div>

<div id="content">
  <a href="" class="open-overlay">Open Overlay</a>

  <p>Hello World</p>
  <p>Hello World</p>
  <p>Hello World</p>
  <p>Hello World</p>
  <p>Hello World</p>
  <form>
    <input type="text">
  </form>
</div>

答案 1 :(得分:1)

您不能像本地对话框一样冻结浏览器应用程序。它们不是用JavaScript构建的,而是用本机代码构建的,并且可能以任何方式影响浏览器应用程序。禁止JavaScript以这种方式影响客户端应用程序。

但是,您可以在浏览器窗口中冻结与页面内容的交互。...

只需在页面上方放置一个div大小的窗口即可,并保持固定位置。这将使用户无法与主页上(其后)的任何内容进行交互。然后,在其上方显示您的模式对话框。当用户清除模态时,将其隐藏起来并隐藏窗口大小的div,从而使主页再次具有交互性。

let modal = document.querySelector(".modal");
let pageCover = document.querySelector(".pageCover");
let main = document.querySelector("main");        

document.getElementById("open").addEventListener("click", function(){
  modal.classList.remove("hidden");
  pageCover.classList.remove("hidden"); 
  main.addEventListener("focus", preventFocus);
});


document.getElementById("close").addEventListener("click", function(){
  modal.classList.add("hidden");
  pageCover.classList.add("hidden"); 
  main.removeEventListener("focus", preventFocus);
});

function preventFocus (evt){
  evt.preventDefault();
}
.hidden { display:none; }

.pageCover { 
  position:fixed; 
  z-index:10; 
  background-color:rgba(0,0,0,.25); 
  width:100vw; 
  height:100vh; 
  top:0; 
  left:0;
}

.modal { 
  position:absolute; 
  z-index:100; 
  background-color:aliceblue;
  border:2px double grey;
  width:200px; 
  height:200px; 
  top:30%; 
  left:30%; 
  text-align:center;
}

.modalTitle {
  margin:0;
  background-color:#00a;
  color:#ff0;
  padding:5px;
  font-weight:bold;
  font-size:1.1em;
}

#close { 
  background-color:#800080;
  color:#ff0;
  border:1px solid #e0e0e0;
  padding:5px 10px;
}

#close:hover { background-color:#c000c0; }
<main>
  <h1>This is some page content</h1>
  <p>And more content</p>
  <button id="open">Click Me To Show Modal</button>
  <div>More content</div>
</main>

<div class="hidden pageCover"></div>

<div class="hidden modal">
  <div class="modalTitle">Modal Title Here</div>
  <p>
    Now, you can only interact with the contents of this "modal".
  </p>
  <button id="close" >Close</button>
</div>