Confirmed
A framework agnostic asynchronous confirmation module.
A very simple promise-like API for easily showing a confirmation and
resolving to the result of the user input. Its main goal is to replace or
enhance the typical window.confirm
and many adhoc event based solutions (see
example below).
Special thanks to FunnelCloud Inc. for graciously providing inspiration, R+D, and support.
License: MIT
Install
Node.js:
npm install confirmed
OR
yarn add confirmed
Browser:
The dist/confirmer.js
is a UMD module compatible with Node.js, AMD
(require.js), and as a browser global.
Requirements
This package uses promises. You environment will need to have a Promise
implementation. Most modern browsers and later versions of Node have such. If
you use this in an environment that does not you will need to include a
polyfill.
Usage
Much like the Promise
API the constructor for the Confirmer
takes
a function. That function is passed a resolver object which has four functions
on it that you can use to fulfill the Confirmer
.
{ // Affirm confirmation resolver; // Reject confirmation resolver; // Cancel confirmation resolver; // Reject with an Error resolver; // Register a disposer function to clean up resources // Same as onDone but in the initializer function closure resolver;}
Each state can take an optional value. The Confirmer
is a wrapper around
a Promise
and can be treated as a promise. For example to capture any errors
or exceptions you may trigger you would use the catch()
function.
{ … } ;
The then()
function will be passed the underlying data object:
{ … } ;
The reason
being one of rejected
, confirmed
, or cancelled
. And the
value
is the value passed to one of the resolver functions.
API
Confirmer
The main class is referred to as Confirmer
though the packaging is called
confirmed
This is simply to prevent an NPM name collision but the proper
term for this utility is Confirmer
and is referenced as such in this
documentation.
Kind: global class
- Confirmer
- new Confirmer(initFn)
- instance
- static
new Confirmer(initFn)
Much like the Promise
API the constructor for the Confirmer
takes a
function. That function is passed a resolver object which has three
functions on it that you can use to fulfill the Confirmer
, one
function to register an error, and a disposer function to clean up
resources is needed. Each fulfillment function can take an optional value.
Example
{ // Affirm confirmation resolver; // Reject confirmation resolver; // Cancel confirmation resolver; // Reject with an Error resolver; // Register a disposer function to clean up resources // Same as onDone but in the initializer function closure resolver;};
Params
- initFn
function
- The initializer function
Confirmer
confirmer.onConfirmed(fn) ⇒ Register callback that is called when resolver.confirm()
is triggered.
Used to denote that the user has confirmed in some way. ("OK" button,
correct login credentials, etc.)
If the callback returns a new Confirmer the result will be that new Confirmer allowing the callback to change the fulfillment reason as part of the chaining. If it is simply a scalar value the fulfillment reason with remain the same but the value will change.
Kind: instance method of Confirmer
Returns: Confirmer
- A new Confirmer instance for chaining
Params
- fn
function
- callback function called when Confirmer is confirmed
Confirmer
confirmer.onRejected(fn) ⇒ Register callback that is called when resolver.rejected()
is triggered.
Used to denote that the user has performed an action that denied the
confirmation. ("No" button, bad password, etc.)
If the callback returns a new Confirmer the result will be that new Confirmer allowing the callback to change the fulfillment reason as part of the chaining. If it is simply a scalar value the fulfillment reason with remain the same but the value will change.
Kind: instance method of Confirmer
Returns: Confirmer
- A new Confirmer instance for chaining
Params
- fn
function
- callback function called when Confirmer is rejected
Confirmer
confirmer.onCancelled(fn) ⇒ Register callback that is called when resolver.cancel()
is triggered.
Used to denote that the confirmation was cancelled and perhaps should do
nothing.
If the callback returns a new Confirmer the result will be that new Confirmer allowing the callback to change the fulfillment reason as part of the chaining. If it is simply a scalar value the fulfillment reason with remain the same but the value will change.
Kind: instance method of Confirmer
Returns: Confirmer
- A new Confirmer instance for chaining
Params
- fn
function
- callback function called when Confirmer is cancelled
confirmer.onCanceled()
Deprecated
Spelling error; use onCancelled
.
Kind: instance method of Confirmer
Confirmer
confirmer.onDone(fn) ⇒ Register a callback that is called when any of the resolver functions are
triggered. This is used for clean up like closing the dialog and removing
stale event handlers. This is also called if the resolver.error()
is
triggered or something throws an exception in the initialization function
(which can be captured by the catch()
function just like a promise).
Kind: instance method of Confirmer
Returns: Confirmer
- A new Confirmer instance for chaining
Params
- fn
function
- callback function called when Confirmer is resolved/errored
Promise
confirmer.then(onFulfilled, onRejected) ⇒ Cast to a Promise
. Will proxy to the internal promise then()
method.
Since the result is a Promise it will not chain as Confirmer after this.
The result of a fulfilled promise is an Object with reason
and value
properties. See resolve for more details of this
internal object.
Kind: instance method of Confirmer
Params
- onFulfilled
function
- callback when internal promise is fulfilled - onRejected
function
- callback when internal promise is rejected
Promise
confirmer.catch(onRejected) ⇒ Cast to a Promise
. Will proxy to the internal promise catch()
method.
Since the result is a Promise it will not chain as Confirmer after this.
Kind: instance method of Confirmer
Params
- onRejected
function
- callback when internal promise is rejected
Confirmer
Confirmer.resolve(result) ⇒ Low level utility to construct a new Confirmer
with a fulfillment. It is
designed to easily wrap the internal promise/resolution in a Confirmer
object.
- if a
Confirmer
is passed it will be returned - if a
Promise
is passed it will become the internal promise of a new Confirmer - if an
Object
is passed it will become the fulfilled value of the internal promise of a new Confirmer
Warning: Any other type will cause the Confirmer to reject with an error.
The internal fulfillment value (either directly of as the result of a promise resolution) must be an Object with these properties:
- reason
String
- the reason for the fulfillment. One of "confirmed", "cancelled", or "rejected". - value
Any
- the value associated (optional)
Kind: static method of Confirmer
Returns: Confirmer
- a new Confirmer that has/will be resolved to the result
Params
- result
Confirmer
|Promise
|Object
- the result the new Confirmer should resolve to
Examples
The following are example situations that I've run into and how this module can help reason about them.
window.confirm
Basic In this example we will wrap the window.confirm
. Although this is not
asynchronous it does illustrate the API.
{ if resolver; else resolver; } ;
jQuery dialog
Here we show how to toggle a modal dialog with jQuery.
{ ; ; ;} ;
Password prompt
Maybe the resolution of the confirmation needs more logic. For example asking for a password.
{ { var passwd = ; if passwd === 'password' resolver; else resolver; } ; ; ;} ;
Auto closing message box
Here is an example of a message box that auto closes after 5 seconds.
Notice that you can call the resolver functions multiple times and only the first one wins.
{ ; ; ;};
Vanilla DOM Events (using the dispose function)
Because vanilla DOM events are a common area for memory leaks the expectation
is that when you addEventListener
you have a corresponding
removeEventListener
. Unfortunately this requires a reference to the event
handler function. This is typically accomplished using named functions.
However, that also adds scope problems and more boilerplate. Some attempt to
use arguments.callee
, some use var _this = this
, and some use outer scoped
variables. This example takes advantage of the dispose
API to make disposing
resources in a cleaner (read prettier) way.
let dialog = document;let buttonYes = dialog;let buttonNo = dialog; { buttonYes; buttonNo; resolver; dialogstyledisplay = 'block';} ;