34

I was developing a GreaseMonkey script which used window.showModalDialog.

But before finishing it, I have discovered that Firefox 29 warns:

Use of window.showModalDialog() is deprecated. Use window.open() instead. For more help https://developer.mozilla.org/en-US/docs/Web/API/Window.open

But the problem is that window.open needs UniversalBrowserWrite privilege in order to open a modal window using window.open.

Then, why is window.showModalDialog deprecated? Is there any API which doesn't require privileges?

Note: I don't want a fake modal dialog (like jQuery's one), I need a real modal which pauses JavaScript execution.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • 1
    Read: [window.showModalDialog: What It is and Why You Should Never Use It](http://tjvantoll.com/2012/05/02/showmodaldialog-what-it-is-and-why-you-should-never-use-it/), [dev.opera: Removing showModalDialog from the Web platform](http://dev.opera.com/blog/showmodaldialog/) – Bergi Aug 12 '14 at 14:21
  • 1
    "I need a real modal which pauses JavaScript execution." Window.showModalDialog() is depreciated precisely because it pauses javascript execution. Pausing javascript execution is difficult to implement securely, and in a way the gives a responsive browser. This is similar to why synchronous XMLHttpRequest is also being depreciated. – Greg Lowe Nov 13 '14 at 22:44

4 Answers4

30

Why is window.showModalDialog deprecated?

From http://tjvantoll.com/2012/05/02/showmodaldialog-what-it-is-and-why-you-should-never-use-it/,

In general the idea of putting a native dialog implementation into the browser was a really good idea, but window.showModalDialog was a bad implementation that is riddled with issues and poor browser support. (...)

Note that (...) [a modal dialog using showModalDialog] is a full HTML document, not a snippet that is injected in. This is a characterizing feature of window.showModalDialog. It’s really just two completely separate windows communicating with each other. The fact that you have two separate windows and DOMs means you don’t have to worry about JS & DOM conflicts, which is appealing if you have a lot of bad JavaScript with a cluttered global scope. But mostly this just adds unnecessary complexity, complicates the browser implementation, and contributes to a number of bugs. (...)

While it’s important that modal dialogs prevent the user from interacting with the originating window, there’s no reason the user shouldn’t be allowed to interact with other tabs or native browser controls (back/forward, favorites, address bar, etc). (...) This is actually a big annoyance to the end user. (...)

The debugging experience for window.showModalDialog is horrible. (...) You're basically forced to alert like it’s 1999 to determine what’s going on. (...)

Currently no major mobile browsers support window.showModalDialog, so if you’re looking for any sort of tablet / mobile support you need to stay away.

What to use instead?

HTML5 introduces the new <dialog> element, which can be used to display dialogs, including modal ones.

For example:

<dialog id="myDialog">
    Foo bar
    <button id="hide">Close</button>
</dialog>
<button id="show">Show Dialog</button>
var dialog = document.getElementById('myDialog');  
document.getElementById('show').onclick = function() {  dialog.showModal();  };  
document.getElementById('hide').onclick = function() {  dialog.close();      };

Demo

The problems are:

  • Browser support is currently negligible, but there is a polyfill.
  • It doesn't pause JS execution.
Oriol
  • 274,082
  • 63
  • 437
  • 513
6

You can use my showModalDialog polyfill using <dialog> tag if you want to still use this solution.

Community
  • 1
  • 1
niutech
  • 28,923
  • 15
  • 96
  • 106
3

Currently, if you don't want to use privileges and want to use modal window, best way is to use jQuery UI Dialog or something similar.

TreeNode
  • 472
  • 1
  • 7
  • 10
  • But jQuery's modal dialog is called *modal* but it isn't *modal*. I need to stop JavaScript execution. – Oriol Dec 22 '13 at 21:08
  • 3
    @Oriol why would you want js execution to pause? Can't you just not do anything until a callback is called? – megawac Dec 22 '13 at 21:16
  • In my previos project, I have a same issue with window.open() and privileges. Because of that we have decided to use jQuery. For preventing execution of js, I can suggest trow() function or somthing like that. – TreeNode Dec 22 '13 at 21:17
  • @megawac Because the javascript I want to pause is not mine, is untrusted javascript from sites (I use it in a GreaseMonkey script). With `showModalDialog` I can pause it and let the user decide if it should be killed or not. If user decides it's not bad, then the script can continue. – Oriol Dec 22 '13 at 21:20
  • @AshotSeropian Well, I meant "pause" instead of "stop" – Oriol Dec 22 '13 at 21:21
  • 1
    Can you apply jQuery's when() and then() methods for simulating some kind of "pause"? – TreeNode Dec 22 '13 at 21:28
  • @AshotSeropian No, because I don't have control over the code I want to pause. – Oriol Dec 22 '13 at 21:48
  • 2
    I'm using the jquery ui method with an iframe that I set the dialogArguments property of from the parent. Any code that was previously executing after the return from showModalDialog, and is based on the popups return value, I changed to be inside an anonymous function that I pass to my dialog method as a callback to execute when the dialog closes. Inside the close event handler of the dialog, I extract whats in the returnValue property. This way the page in the dialog, along with the code that was previously paused, doesn't require any modifications. – Kevin Heidt Sep 07 '14 at 21:24
  • @Oriol It sounds like what you're trying to do should be written as a full fledged browser extension, and not as a GreaseMonkey script. Javascript that stops and restarts other javascript sounds pretty dangerous (all inside of javascript). – Ryan Shillington Sep 09 '14 at 15:54
  • @Kiquenet I didn't find any alternative which pauses JS. Other than that you can use `` elements or jQuery ones. – Oriol Jan 30 '17 at 09:13
  • @Oriol maybe too late response. Modal dialogs have nothing to do with internal program execution pausing. They may be related, but only due to specific implementation. – Rustem Zinnatullin Nov 22 '19 at 06:33
-1

To block script execution, use while (true) { }. The fact that this is equivalently bad behavior to showModalDialog is part of the reason they removed showModalDialog.

Also, "modal" and "blocking script execution" are not the same thing. "Modal" simply means on top of everything else, preventing you from interacting with those things. So jQuery UI dialogs are modal, they just don't block script execution.

Domenic
  • 110,262
  • 41
  • 219
  • 271
  • 4
    Uhm, but `while (true) { }` is CPU intensive, isn't it? And if I do that, the page (or even the browser) will freeze, so the dialog will be unusable too. I want to pause only the page, not the dialog. – Oriol Mar 12 '14 at 17:50
  • You can't to stop this loop execution, because js is one-threaded. Opened with `window.open` windows still use same thread, and will be full frozen(you probably even never see them) – vp_arth Dec 17 '14 at 14:11