Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safari 5.1 prompt() function and cancel

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?

like image 249
Anomie Avatar asked Sep 08 '11 16:09

Anomie


3 Answers

var res = prompt('hello?', '')
if (res === null || res === '' && isSafari && confirm('was that cancel?'))
    cancel
like image 69
Anonymous Avatar answered Nov 02 '22 04:11

Anonymous


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.

like image 27
kennebec Avatar answered Nov 02 '22 06:11

kennebec


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.

like image 2
Anomie Avatar answered Nov 02 '22 04:11

Anomie