te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - How to freeze browser window intentionally (like alert, confirm and prompt does)? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to freeze browser window intentionally (like alert, confirm and prompt does)? - Stack Overflow

programmeradmin3浏览0评论

Is there any way of freezing the browser window intentionally like alert, confirm and prompt (in short: "acp") does?

I want to show a modal dialog with custom css instead of the native popups for "acp" but also want to have the ability to freeze the browser until I have users feedback just like "acp".

But man, why? This is bad practice (uh I have to downvote)!
So when it is bad practice - then why does "acp" actually offer this synchronous behavior? Because in some particular scenarios its just exactly the right tool for an appropriate UX. Those native modals do look so ugly and are also very limited at the same time.

Here's just one quick and dirty example where it would be totally fine to freeze the browser until the user gives feedback. Lets say we have a form with an input[type="reset"]-element. So before we really let the form reset we ask the user something like: "Are you sure you want to reset (data will be lost)?".

If I would be fine with the native modal look (which I'm not) I could do:

document.querySelector('form').addEventListener(
  'reset', e => confirm('Are you sure you want to reset (data will be lost)?') || e.preventDefault()
);
<form>
  <input placeholder="type something, reset and cancel to keep input value" style="width:100%">
  <input type="reset">
</form>

Is there any way of freezing the browser window intentionally like alert, confirm and prompt (in short: "acp") does?

I want to show a modal dialog with custom css instead of the native popups for "acp" but also want to have the ability to freeze the browser until I have users feedback just like "acp".

But man, why? This is bad practice (uh I have to downvote)!
So when it is bad practice - then why does "acp" actually offer this synchronous behavior? Because in some particular scenarios its just exactly the right tool for an appropriate UX. Those native modals do look so ugly and are also very limited at the same time.

Here's just one quick and dirty example where it would be totally fine to freeze the browser until the user gives feedback. Lets say we have a form with an input[type="reset"]-element. So before we really let the form reset we ask the user something like: "Are you sure you want to reset (data will be lost)?".

If I would be fine with the native modal look (which I'm not) I could do:

document.querySelector('form').addEventListener(
  'reset', e => confirm('Are you sure you want to reset (data will be lost)?') || e.preventDefault()
);
<form>
  <input placeholder="type something, reset and cancel to keep input value" style="width:100%">
  <input type="reset">
</form>

So "everybody" should agree (edit: or at least somebody could) this isn't bad practice, right?
But how can we achieve the same with a custom styled modal/dialog/popup?
I'm -of course- not asking for the HTML/CSS part but for the capability of freezing the browser window via JavaScript!

To be honest, I actually expect some downvotes for this but maybe there is this one Killer JavaScript Ninja, who have this one special hack to make it possible...

Share Improve this question edited Dec 7, 2022 at 15:43 Axel asked May 1, 2019 at 21:27 AxelAxel 3,32311 gold badges37 silver badges59 bronze badges 19
  • 3 So "everybody" should agree this isn't bad practice, right? No, no I don't. Just because an old native method froze the browser, doesn't mean you're logic should. Preventing users from interacting with the page, does not mean you have to freeze the browser. The entire concept of overlays exists for this very purpose. – Taplar Commented May 1, 2019 at 21:32
  • 2 You can't, but you can make it look like you have. If you look at Bootstrap modals for example. getbootstrap./docs/4.0/ponents/modal In your example, instead of using a reset button, just show your modal, and then call the reset on the form manually. – Keith Commented May 1, 2019 at 21:33
  • 1 "So when it is bad practice - then why does "acp" actually offer this synchronous behavior? Because in some particular scenarios its just exactly the right tool for an appropriate UX." I have never met a UXer who has championed freezing the browser and removing user control as a positive experience. – Taplar Commented May 1, 2019 at 21:39
  • 2 Not sure what answer you want,. It's not possible. The main reason been if you freeze the browser, what is it you think will render the UI, you have just blocked the browsers event loop, it won't be able to handle any input from the user. Synchronous methods do feel nice, but if you use async / await, you could do const sure = await showConfirm();, all it needs is your confirm dialog to be a promise. – Keith Commented May 1, 2019 at 21:45
  • 2 Yes, that's why I said you call it manually. That's how I do it anyway, doesn't seem to make code that much more plicated, especially if your someone who is quote quite experinced.. – Keith Commented May 1, 2019 at 21:57
 |  Show 14 more ments

2 Answers 2

Reset to default 6

You can't freeze the browser application like the native dialogs do. Those are not built with JavaScript, they are built with native code and can affect the browser application in any way. JavaScript is prohibited from affecting the client application in such ways.

But, you can freeze interactions with your page content within the browser window....

Just place a window sized div above the page with fixed positioning. That will prevent the user from being able to interact with anything on the main page (behind it). Then, display your modal dialog on top of that. When the user clears the modal, hide it and the window sized div, thus making the main page interactive again.

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>

You can place everything within a div except for your popup. You can then turn on/off pointer events via css.

Everything within the div will no longer be interactable. This will give the appearance of freezing the browser window.

.freeze { pointer-events: none; }

Note: When adding pointer-events to an element this affects all child elements as well, so placing it on the body would also lock the popup.

Once the popup has been closed, we can remove the freeze class from the div and everything will start working again.

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>

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论