How to fix window.prompt in Internet Explorer

From Trephine

Jump to: navigation, search
« Why applets continue to fail, part 2 Tech startups start with a question. What's yours? »

[subscribe] Recent blog entries

Live Demos

How to fix window.prompt in Internet Explorer

This article explains how to fix the two main problems with window.prompt in Internet Explorer:

  1. Only the first two lines of the message are displayed, and
  2. In IE 7 and above, prompt is effectively blocked - the browser issues a security warning instead.

No, this is not another DHTML solution - you'll be able to call window.prompt() from JavaScript just like you've always wanted to, and it will show the user an native system dialog.

Update: It turns out InputBox is blocked in IE 7, so this only works for IE 6. Sorry for the confusion - if there's a solution to this and I find it, I'll update this post accordingly.

I came up with this solution while developing trephine's math challenge. Unfortunately, I couldn't guarantee that it isn't tampered with prior to issuing the dialog to the user. Mine is an extreme edge-case however in that the DOM itself is an untrusted environment - this will work just fine for everyone else.

The Solution

Brace yourself for what I'm about to tell you, because your first instinct will be to run away in horror. (It's a good idea to put that coffee down as well, lest you spray it across your LCD).

We're going to use ... VBScript.

Still with me? Great! As it turns out, one "feature" of Internet Explorer is that JavaScript (JScript to be accurate) cannot modify native methods such as window.alert and window.prompt, but VBScript has no such limitation. Therefore we'll use VBScript to define a new prompt function, which we can then call from JavaScript.

The key bit of VBScript we need is this:

Function prompt(m,d)
  prompt=InputBox(m,"Explorer User Prompt",d)
End Function

The snippet above replaces the global prompt function (that is, window.prompt) with a custom wrapper function that launches an InputBox. The InputBox method creates a modal input dialog much like the normal window.prompt, but without its limitations.

The most straightforward way to implement this would be to slap the Function declaration inside a pair of <script> tags with type set to "text/vbscript", but then you'd have to have VBScript on every HTML page (yuck). Fortunately, there's a workaround for this too.

Code and live demo

To dynamically load the VBScript code from JavaScript, we create a script DOM node with the appropriate type and text, append it to the document.body, and then remove it once it has been executed:

(function(){
  var vbs = document.createElement('script');
  vbs.setAttribute('type', 'text/vbscript');
  vbs.setAttribute('text', [
    'Function prompt(m,d)',
    'prompt=InputBox(m,"Explorer User Prompt",d)',
    'End Function'
  ].join("\n"));
  vbs.onreadystatechange = function(){
    if (this.readyState=='complete') document.body.removeChild(vbs);
  };
  document.body.appendChild(vbs);
})();
< execute this code >

And here's a simple example to demonstrate (execute the above script first):

(function(){
  var name = prompt([
    "What's your name?",
    "",
    "This and all subsequent lines would be invisible were it not for the InputBox fix.",
  ].join("\r\n"), "John Jacob Jingleheimerschmidt");
  alert("You entered: " + name);
})();
< execute this code >

Ta-da!

Hiding from non-IE browsers

Although the above would have no effect in other browsers, you may want to wrap it in conditional logic so that it's ignored everywhere but IE. The easiest and most fool-proof way to do that is to use a little known feature of JScript called Conditional Compilation.

Here's the code again, using conditional compilation to ensure that it only executes in IE:

/*@cc_on @if (@_jscript) (function(){
  var vbs = document.createElement('script');
  vbs.setAttribute('type', 'text/vbscript');
  vbs.setAttribute('text', [
    'Function prompt(m,d)',
    'prompt=InputBox(m,"Explorer User Prompt",d)',
    'End Function'
  ].join("\n"));
  vbs.onreadystatechange = function(){
    if (this.readyState=='complete') document.body.removeChild(vbs);
  };
  document.body.appendChild(vbs);
})(); @end @*/
< execute this code >

Caveats and gotchas

One minor problem with this solution is that VBScript does not have any concept of optional function parameters or default parameter values. This means that our replacement prompt function requires both parameters: a message and a default value. Without the second parameter, calling prompt would result in an exception being thrown.

Of course, creating a wrapper function in JavaScript is no problem:

var $prompt = function (m,d){ return prompt(m,d||''); };

But then you have to call $prompt everywhere you'd otherwise call prompt. It's half of one or six dozen of the other, as they say.

Another gotcha is that the replacement code must be run before the first call to window.prompt. If window.prompt is called before the replacement code runs, JScript will "bind" to the original window.prompt and ignore the overwrite attempt.

Finally, I have not tested this technique in any version of IE other than 6. If you're running other versions, please leave a comment and let me know how it works!

Update: As mentioned in the opening section, this doesn't actually prevent the security dialog in IE 7, although it does solve the line truncation problem. If there is a solution to the security dialog (I'm beginning to doubt that there is), I will update this post.

Thanks for reading - as always I look forward to your feedback.

Explicit public domain declaration

Just so there's no confusion: all of the code snippets on this page are provided "AS IS", without warranty of any kind, express or implied.

All of the code snippets on this page are hereby released into the public domain by the me, the copyright holder. This applies worldwide. Or in case this is not legally possible: The copyright holder grants any entity the right to use this work for any purpose, without any conditions, unless such conditions are required by law.

If you'd feel better with a "real" license, you're free to use code snippets on this page under the MIT license as described on the about page.

Any links back to this site are always appreciated, but not required. Enjoy!

--Jim R. Wilson (jimbojw) 14:12, 2 March 2009 (UTC)