16

In most browsers (including older versions of Safari), the Javascript prompt function returns null when the user clicks "Cancel", and the empty string if the user clicks "Ok" with nothing in the text box. But in Safari 5.1, it returns the empty string for both cases.

I used Safari's "report a bug" feature to report it to Apple, but who knows when they might even acknowledge it much less fix it. Does anyone have a workaround?

Anomie
  • 92,546
  • 13
  • 126
  • 145
  • Same bug at 7.1 safari version and 8.0. w3school explain that's supported by safari hahahaha the good joke... – bArraxas Jul 09 '18 at 08:53

5 Answers5

3
var res = prompt('hello?', '')
if (res === null || res === '' && isSafari && confirm('was that cancel?'))
    cancel
Anonymous
  • 31
  • 1
3

I appreciate the heads up- I hadn't noticed the behavior, but now I see that you are correct. Safari 5 behaves normally, 5.1 returns an empty string for either button click, if there is an empty string in the prompt field.

My only suggestion is to put a space character in the field to start with. Only the 'OK' button will return the space, cancel will return null or the empty string.

var p=prompt('what dya say?',' ');
if(!p)// cancel was *probably* clicked
else if(p===' ')//ok was clicked with no input
else// there is user input

The user could start to enter something, delete it, and then hit 'ok' instead of cancel, but that kind of case may as well be a cancel.

kennebec
  • 102,654
  • 32
  • 106
  • 127
2

I've managed to come up with a real workaround, since Safari added support for showModalDialog() in 5.1. Awfully convenient, that.

First, create a file with this content:

<html>
<head>
<title>Prompt</title>
<script type="text/javascript">
function a(){
        if(window.dialogArguments.length > 0)
                document.getElementById('a').textContent = window.dialogArguments[0]+'\n\n';
        if(window.dialogArguments.length > 1)
                document.getElementById('b').value = window.dialogArguments[1];
        document.getElementById('b').focus();
}

function s(b){
        window.returnValue=b?document.getElementById('b').value:null;
        window.close();
}

function kp(e){
        if(!e.DOM_VK_ENTER) e.DOM_VK_ENTER=13;
        if(!e.DOM_VK_RETURN) e.DOM_VK_RETURN=13;
        if(!e.DOM_VK_ESCAPE) e.DOM_VK_ESCAPE=27;

        switch(e.keyCode){
          case e.DOM_VK_ENTER:
          case e.DOM_VK_RETURN:
            if(e.preventDefault) e.preventDefault();
            if(e.stopPropagation) e.stopPropagation();
            e.returnValue = false;
            e.cancelBubble = true;
            s(1);
            return false;

          case e.DOM_VK_ESCAPE:
            if(e.preventDefault) e.preventDefault();
            if(e.stopPropagation) e.stopPropagation();
            e.returnValue = false;
            e.cancelBubble = true;
            s(0);
            return false;

          default:
            return true;
        }
}
</script>
<body style="text-align:center;white-space:pre-wrap" onload="a()">
<span id="a"></span>
<input type="text" id="b" onkeydown="return kp(event)" /><input type="button" value="Ok" onclick="s(1)" /><input type="button" value="Cancel" onclick="s(0)" />
</body>
</html>

Then, for broken versions of Safari (there seems to be no way to feature-detect this without popping up a prompt and asking the user to hit "Cancel", so you'll probably have to do a User-Agent check), execute the following Javascript to replace window.prompt:

(function(){
        if(window.console && window.console.log)
                window.console.log('Applying bugfix for Safari 5.1\'s prompt()');
        var oldprompt = window.prompt;
        window.prompt = function() {
                return showModalDialog(location.protocol+'//'+location.host+'/js/safari-5.1-bugfix.html', arguments);
        };
        window.prompt.$orig = oldprompt;
})();

Of course, change the path /js/safari-5.1-bugfix.html to the correct path to the above-created HTML file on your server. Unfortunately, we cannot use a data: URI as Safari apparently has another bug where it loses window.dialogArguments and ignores window.returnValue for dialogs with data: URIs.

You can then use prompt() as you normally would.

Anomie
  • 92,546
  • 13
  • 126
  • 145
0

I tryed and this worked for me

    var location="";
    var p=prompt("type your location",location ); 

if(p!==null)   {    location = p;    alert("ok do query");   }
Miguel
  • 3,349
  • 2
  • 32
  • 28
-1

Sure, two in fact.

First the obvious one, redesign your system so an empty string is not a valid response. Think about it, when in a conversation is it acceptable for one guy to stare at you blankly in actual answer to your question?

The second one is to use modal dialogs, like jQuery ones, to ask for this information. You'll get complete control over it and the application won't look like it was made in 1996.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • 4
    Your first answer is useless. There are many reasons an empty string might be a valid response. Your second isn't terribly useful either, I'm not about to dig through JQuery's source trying to find out what it might be doing for a "modal dialog". – Anomie Sep 08 '11 at 16:43
  • The theory is pretty simple, you put a "large" `div` covering the whole viewport then display your dialog over it. On closing the dialog, you remove the `div` you created earlier. It's all encapsulated in a simple `.dialog('show')` call though! – Blindy Sep 08 '11 at 16:49
  • 1
    But you can't use that style of dialog as `var retval = dialog('show')`. You would have to set up callbacks for your pseudo-dialog to be called when the user clicks "Ok" or "Cancel" and break your prompting function into pieces for "before" and "after" the display of the dialog while maintaining state between the two. When I want that sort of thing, I do it already. But sometimes a simple `prompt()` is all that is needed to ask the user for the necessary information. – Anomie Sep 08 '11 at 16:55