A cross-browser JavaScript prompt

You might be looking at the title of this entry and say “Well, DUH! JavaScript’s prompt() is already cross-browser!”

While working on a project earlier today, I discovered a nasty little problem… Internet Explorer v7 (IE7) disables prompt() by default! This means you can’t rely on prompt() being available in IE7 when building your online applications.

In most cases, prompt() should be avoided altogether. Maybe Microsoft was right in disabling prompt(), since so many malicious sites take advantage of it. However, I had a legitimate use for it today, and was very irked to find out it won’t work in IE7. (I develop in Firefox and IE6, which might explain to some of you why I’m late to the party with discovering this limitation in IE7.)

After googling for a while — yes, I use google as a verb — it appears quite a few people have developed workarounds for the prompt() limitation in IE7. Most of them were bulky or required a bit too much hacking for my tastes. There were a few nice examples [link no longer available] out there, but in the end, I decided to make my own workaround using Microsoft’s proprietary showModalDialog function.

Microsoft’s showModalDialog allows the developer to load an external HTML file into a generated window and give it focus. The user can’t click back to the original document until they’ve closed the modal window, just like a prompt(), alert(), or confirm(). The generated window behaves much like a pop-up window (it can be sized, show/hide scrollbars, etc.), but to my knowledge, modal windows aren’t blocked by pop-up blockers.

I’ll admit that using an external HTML page feels like a big disadvantage compared to a simple prompt(). However, one potential advantage showModalWindow provides is the ability to style the faux prompt window; in IE, the prompt window has always looked and behaved a little different from any of the other dialog windows (alert, confirm). Now we can have it visually fit in with the rest of the family! Due to this styling issue, and to make my life easier, I decided to use showModalWindow on all versions of IE, not just IE7.

Native IE6 prompt:
Native IE6 prompt

Native Firefox 2 prompt:
Native Firefox 2 prompt

New faux prompt, as seen in IE6:
Faux prompt, IE6

New faux prompt, as seen in IE7 (WinXP):
New faux prompt, as seen in IE7 (WinXP)

Important note: The IE7 modal window will forcibly display the address and status bars if being called by a server (not localhost) which isn’t listed in that user’s list of ‘Trusted Sites.’ This is annoying, but still better than having no prompt() at all. IE6 forcibly displays the status bar, but not the address bar.

Example

Before I dig into the code, here’s a functioning example. There are two files involved in this hack: the main HTML page calling the prompt, and the faux prompt HTML page.

The traditional prompt()

For those of you new to using prompts, here’s an example of a traditional prompt in action:


window.onload = function (){
   var name = prompt("Please enter your name", "");
   if(name){
      alert("You entered '" +name +"'.");
   }
}

Return values

A key feature of prompt() is that it returns the value of the textfield as a string. If nothing was typed into the text field, prompt() returns either null or false, depending on your browser. If the user clicks ‘cancel’, prompt() returns false.

Our faux prompt for IE needs to work the same way. As luck would have it, showModalWindow allows us to specify return values.

Prompt text

Another key feature of prompt() is the ability to display your own text in the prompt, such as “Please enter your name.” To make our lives easier, our faux prompt should work the same way, using the same syntax.

Our IE-specific function: iePrompt()

In all its glory:


function iePrompt(str){
   var settings = "dialogWidth: 290px; dialogHeight: 160px; center: yes; edge: raised; scroll: no; status: no;";
   return window.showModalDialog("iePrompt.html", str, settings);
}

Let’s break it down.


function iePrompt(str){

Since we can’t use the traditional prompt(), we need to create a new, similar function. Just as prompt allows you to specify what text will display by passing a string,

prompt("This text will display in my prompt","")

we want to be able to pass a string in our new function:

iePrompt("This text will display in my prompt")


var settings = "dialogWidth: 290px; dialogHeight: 160px; center: yes; edge: raised; scroll: no; status: no;";

IE’s showModalDialog allows you to style the window much like a pop-up window. The settings are entered as a single string. For convenience and readability, I placed all the settings in a variable named “settings”. You can tweak these settings to suit your own needs. A list of optional parameters can be found here.

Important note: The height of the modal window is set here using dialogHeight; if the display text (in this case “Please enter your name”) wraps to the next line, the window will NOT expand to fit it. If you’re working with long strings, you’ll need to test the height of your modal window, or develop your own sizing routine. Also note that in IE6, dialogHeight referred to the height of the entire dialog window. In IE7, the model was changed, and dialogHeight now refers ONLY to the height of the content. See this IEBlog for more info.

return window.showModalDialog("iePrompt.html", str, settings);

As mentioned earlier, showModalWindow can return a value the same way prompt() returns a value. We want our iePrompt() function to pass the value returned by showModalWindow.

  • iePrompt.html is the name/path of the HTML file containing a form that mimics prompt().
  • str is the text that will be displayed in the prompt.
  • settings is the variable containing the settings string we defined earlier.

The iePrompt.html file

I don’t want to spend too much time explaining the HTML file, as it’s a simple HTML file containing a wee bit of CSS for styling, and a very tiny form. There are some important elements to note, though.

The submit function


function formSubmit(){
   var str = document.getElementById("promptText").value;
   if(str){  
      window.returnValue = str;
   } else {  
      window.returnValue = false;
   }
   window.close();
}

In order to get the showModalDialog function to return a value, we have to make our form return a value. To do this, we have to specifically use window.returnValue. The code is set up to conditionally send either the content of the promptText field, or the value false, just like a normal prompt.

After returning the value to the page that called the prompt, we need to close the modal window by calling window.close.


function formCancel(){
   window.returnValue = false;
   window.close();
}

Prompts also have cancel buttons. We want our modal window to have a cancel button that behaves just like a prompt. To do this, we set up a function that returns the value false and closes the modal window.


window.onload = function (){
   var str = window.dialogArguments;
   if(str){
      document.getElementsByTagName("label")[0].innerHTML = str;
   }
}

This bit of code grabs the display text value being passed by iePrompt and dynamically inserts it into a label on our form. We’re passing the argument using the dialogArguments property of the modal window generated by showModalDialog.


<body onbeforeunload="formCancel();">

Lastly, we need to take into account the fact that many people choose to click the dialog window’s close button (X) instead of OK or Cancel. Using onbeforeunload allows us to call formCancel() if the user decides to close the window.

And that’s it! We now have a functioning prompt for IE.

Putting it into action

Now that we have our custom IE prompt, we need to integrate it with non-IE browsers. Fortunately, this is a pretty simple task.

Determining if the browser is IE

Rather than use some elaborate browser-sniffing technique, we’ll stick to supported feature detection, which is considered a best-practice by the DOM scripting crowd. This is easily accomplished by checking for window.showModalDialog. If the return value is true, the browser is a flavor of Internet Explorer (v4 and higher), and supports our new prompt method. If the return value is false, the browser isn’t IE and should be able to use a traditional prompt().


function cbPrompt(str){
   try {
      if(window.showModalDialog){ return iePrompt(str); }
         else { return prompt(str, ""); }
   } catch (e) { 
         return false; 
   } 	
}

I decided to use a try/catch statement for future expandability (being able to add extra functionality, such as using confirm() to validate the text entered by the user. You could rewrite it to use simple if/else statements.

I wrapped the logic into a new function called cbPrompt (“cb” meaning cross-browser). Now anytime I need a prompt, I simply call cbPrompt instead of prompt():


window.onload = function (){
   var name = cbPrompt("Please enter your name");
   if(name){
      alert("You entered '" +name +"'.");
   }
}

As you can see, it’s almost exactly the same as using the traditional prompt:


window.onload = function (){
   var name = prompt("Please enter your name", "");
   if(name){
      alert("You entered '" +name +"'.");
   }
}

Just remember that you have to ensure the iePrompt.html file is present and that the path defined in the iePrompt function is accurate.

Here’s a fully-functional cross-browser example.

New SCORM ebook coming soon!

I'm writing an ebook explaining how to build an HTML-based SCORM course. Subscribe to be notified when it's ready, as well as receive early bird pricing and some free goodies!

No spam, no sharing your email address, unsubscribe at any time. Powered by ConvertKit
Advertisements

8 Replies to “A cross-browser JavaScript prompt”

  1. OR…

    Simply instruct your visitors to use a FF browser and provide them the link! (That’s what I did)

    The sooner everybody sends the IE browser to the digital trash can, the better off we all will be!

  2. I’m sure many people agree with that sentiment, but remember there are other browsers out there, too, namely Opera and Safari.

    Opera currently has a huge foothold in the mobile browser market and can’t be ignored. Getting scripts and CSS to behave the same in Opera as they do in Firefox can sometimes be as big of a challenge as wrestling with them in Internet Explorer. 🙂

    Safari isn’t as hard to work with, but it has its moments, too.

  3. Hi Philip,

    cbPrompt very useful! However it doesn’t seem to give focus to the input box. I have tried to do this – I thought it would be simple, but my attempts don’t work. How would you do it??

    Best Wishes,

    Mike

  4. @mike

    the trick is to add a .focus() call in the prompt HTML file. I’ve updated my example to include .focus(). haven’t tested it in all browsers, but it works fine in IE6 and FF 3.6.

  5. With Chrome v5.0.375.99 your script does not seem to work. Whether you click OK or CANCEL, formSubmit() is called immediately after the formCancel() call (and yes return false; is in the form handler.

    Further, window.showModalDialog is true on Chrome.

  6. @adrian Thanks for the tip. I’m not surprised to hear it’s misbehaving in newer browsers… after all, it’s been three years since I wrote this post, and a ton has happened in the browser world in that time (major updates were introduced with Safari 4, Firefox 3.6, Opera 10.5, and IE 8/9, and as you mention now we have the new kid on the block, Google Chrome). I’ll try to test/update the script if I can find some time.

    were you using Chrome proper, or Chrome Frame for IE?

Comments are closed.