5

Possible Duplicate:
How to create TRULY modal alerts/confirms in Javascript?

TL;DR: I've overridden the default alert() function with a custom HTML based one. I want the new dialogue to still block execution, and get the buttons within my dialogue to return true or false from the call to alert() to use in logic (and continue execution).


I'm trying to implement a custom alert box, which replaces the default browser alert with a nicely themed box with the same (or similar) functionality.

I've read this question, and I'm using the solution given in this answer (to the same question). What I want to do now is get my overridden alert to return a true or false value for use in if() statements, depending on whether OK or Cancel was clicked:

if(alert('Confirm?') {
    // Do stuff
}

However, due to having custom HTML instead of a normal alert I can't do this for two reasons:

  • I can't return a value from the buttons in the replacement dialogue (click events bound with $.on()) because I have no idea how to.
  • I can't block program flow with this alert, as far as I know.

I've bound $.on() events to the Cancel and OK buttons in the replacement dialogue which hide the box. These work fine, but the problem I have now is returning a value when a button is clicked, so that execution will halt until an action is taken by the user.

HTML:

<div class="alert background"></div>

<div class="alert box">
    <div class="message"></div>

    <hr>

    <div class="buttons">
        <input type="button" name="cancel" value="Cancel">
        <input type="button" name="confirm" value="OK">
    </div>
</div>

Current JavaScript: (pretty much a carbon copy of the answer in my linked question)

(function () {
    nalert = window.alert;

    Type = {
        native: 'native',
        custom: 'custom'
    };
})();

(function (proxy) {
    proxy.alert = function () {
        var message = (!arguments[0]) ? 'null' : arguments[0];
        var type = (!arguments[1]) ? '' : arguments[1];

        if (type && type == 'native') {
            nalert(message);
        } else {
            // Custom alert box code
            console.log(message);
        }
    };
})(this);

Ideally, I want to be able to put something like this in the // Custom alert box code part:

$('.alert.box input[name="confirm"]').on('click', function() {
    // Hide dialogue box - I can do this already

    // *** Return `true` or other truthy value from 
    // alert for use in `if()` statements
});

So that when the OK or Cancel button is clicked, it removes the custom alert box and returns a true or false value from the call to alert(). I can already remove the alert with $.fadeOut() and $.remove(), that's easy. What isn't is knowing how to get the button click events to get alert() (overridden) to return something.

I've tried to be as clear as I can, but I may have missed something out. Please let me know if I have.

Community
  • 1
  • 1
Bojangles
  • 99,427
  • 50
  • 170
  • 208
  • I think this is fundamentally impossible because the browser's default dialogs are the only things that can be modal in JS. An idea of an modal dialog doesn't seem to exist in JavaScript – Pekka Jan 14 '12 at 22:16
  • What do you know, I asked [the same thing](http://stackoverflow.com/questions/1820564/how-to-create-modal-alerts-confirms-in-javascript) a while back. – Pekka Jan 14 '12 at 22:18
  • @Pekka I had a look at the recommendations as I was typing my question, but couldn't find any relevant ones. The answers to your questions seem to focus around using a framework, or a very browser-specific version. I was looking for a cross-platform solution. – Bojangles Jan 15 '12 at 00:56
  • the problem with the answers to my question is that they don't answer it :) As is the case here now. Using a callback is cool and usually a viable solution, but I'd still like to know whether there is any way to have really modal custom dialogs in JS somehow - I may put a bounty on mine – Pekka Jan 15 '12 at 10:58

2 Answers2

4

The example below shows an approach to creating a custom alert and handling the outcome of the user selection

/*
  message = String describing the alert
  successCallBack = callback function for when the user selects yes
*/
function exampleAlert(message, successCallback)
{
    /*Alert box object*/
    var alertBox =  document.createElement("div");

    /*Alert message*/
    var msg = document.createElement("div");
    msg.innerHTML = message;

    /*Yes and no buttons
      The buttons in this example have been defined as div containers to accentuate the customisability expected by the thread starter*/
    var btnYes = document.createElement("div");
    btnYes.innerHTML= "Yes";

    /*Both yes and no buttons should destroy the alert box by default, however the yes button will additionally call the successCallback function*/
    btnYes.onclick = function(){      $(this.parentNode).remove();successCallback();}
    var btnNo = document.createElement("div");
    btnNo.innerHTML= "No"
        btnNo.onclick = function(){ $(this.parentNode).remove();}

   /*Append alert box to the current document body*/
   $(alertBox).append(msg, btnYes, btnNo).appendTo("body");
}

function test()
{
   alert("Example alert is working, don't use this test as a replacement test - horrible recursion!")  
}
exampleAlert("shoe", test)

This is fairly basic and doesn't allow for additional data to be supplied to the callback function and for that reason is not ideal for production however jQuery's .bind() and similar methods allow for data to be associated with the callback method

It's worth commenting that while the above demonstrates a full implementation of the problem, there are in fact only two lines that actually matter.

btnYes.onclick...
btnNo.onclick...

Since we're achieving the desired result by binding onclick events for true and false respectively, everything else is there to paint the picture.

With that in mind it is possible to effectively turn any container object with at least one sibling into an alert box for eaxmple:

   <!-- Example html -->
   <div id='a'>
      <ul>
         <ul>
            <li>Something</li>
            <li>Something Else</li>
            <li id='yesIdentifier'>Something not necessarily suggesting a trigger?</li>
         </ul>
      </ul>
   </div>  

As long as your yes / no (if no exists) options destroy the appropriate container a converting a container into an alert box can be handled in a couple of lines of code.

$('#yesIdentifier', '#a').click(
        function(){ someCallback(); $(this).closest('#a').remove()});

Neither of the above are exemplary models for implementation but should provide some ideas on how to go about the task.

Finally... do you really need to replace the native alert method? That is, either you're writing the alert calls, in which case you'd know to use your custom method, or you're overwriting default behaviour that you can't guarantee the other developers will be aware of.

Overall recommendation:

I feel the best approach to this would be to create a jQuery plugin which creates the custom alerts on the fly and track callbacks, results and what not within the plugin.

SOliver.

CBusBus
  • 2,321
  • 1
  • 18
  • 26
  • Thanks very much for this answer. I was trying to override the default `alert()` behaviour mainly so I could just write `if(alert('Yes?'))` and do away with more LOC. Alas, it can't be done so I've used your solution here with callbacks. The point you make about developers is void in this situation as I'm doing this on my own, however it is a very good one, so thank you. I've written my own function (not called `alert()`) to deal with custom alerts. – Bojangles Jan 15 '12 at 00:54
  • This is nice, but it isn't really a solution for a *modal* dialog, either. – Pekka Jan 15 '12 at 10:56
1

Why don't you just use a confirm box like so.

var c = confirm('Confirm?');

if(c)
{
    // Yes clicked
}
else
{
    // No clicked
}

Or you could use jQuery UI's dialog confirmation box.

http://jqueryui.com/demos/dialog/#modal-confirmation

brenjt
  • 15,997
  • 13
  • 77
  • 118
  • I might not have said so explicitly, but my question is asking about how to _replace_ the browser's `alert()` function, not just use it's return value. – Bojangles Jan 15 '12 at 00:39
  • @JamWaffles I just updated my question. You could use jQuery UI's dialog box – brenjt Jan 15 '12 at 00:42
  • Thanks for the recommendation, but I'd rather not use jQuery UI, especially considering I've written my own dialogue anyway using SOliver's solution as a base. Thank you for your help nonetheless. – Bojangles Jan 15 '12 at 00:51
  • He can't use jQuery UI's dialog box if he wants a truly modal solution. – Pekka Jan 15 '12 at 10:56