This plugin is obsolete. See the new status
at github.bililite.com/status.
Updated 2015-01-19 to allow $(console).status()
. Now at version 1.4.
Updated 2013-12-18 to use Promise
s. This necessitated removing the result
option and adding the returnPromise
.
Updated 2014-01-09 to add initialText
option and to document the markup used.
For the Kavanot editor I wanted to have a way to display messages (like "Text saved successfully") that would show up on screen then fade out, and a way to enter text (like the title, or editing commands if I ever get that working). I packaged that all together into a plugin could handle both, with an anticipated use like:
<textarea id=editor></textarea>
<div id=notifications></div>
And then do something like $('#notifications').status('Text saved');
and that briefly shows the message in the <div>
and then gradually fade out.
And for user input,
$('#notifications').status({
prompt: 'File Name:',
run: function (text) {
/* do something with text */
if (successful) return 'success message';
if (! successful) throw {message: 'failure message'};
}
});
displays the prompt and an input box then runs the function and displays the result (it automatically catches
the throw
n exception).
See the code on github.
See a demo.
status(message [, classname [, opts]])
There are two ways to use status
. The simpler is $(element).status(message [, classname [, opts]])
which displays the string $('<span>').text(message).addClass(classname).hide().prependTo(element)
, then calling opts.show
, then opt.hide
on that <span>
, then removing it entirely.
Parameters
message
{String}- The message to be displayed
classname
{String}- The class to be applied to the message. Default:
""
(empty string). opts
{Object}- The options, all optional:
show
{Function}- Function to be called to show the message. Called as
opts.show.call(jQuery_object_with_message);
. Default:$.fn.show
. hide
{Function}- Function to be called to hide the message. Called as
opts.hide.call(jQuery_object_with_message);
. Default:function() {return this.fadeOut(5000)}
.
status(opts)
The other way to use status
is to pass a complete set of options including a function to return the message for display.
Options
show
{Function}- Function to display the message, as above.
hide
{Function}- Function to hide the message, as above.
successClass
{String}- Class to be applied to the displayed message if the
run
returns without throwing an exception (passed toclassname
as above). Default"success"
. failureClass
{String}- Class to be applied to the displayed message if the
run
throws an exception (passed toclassname
as above). Default"failure"
. run
{Function}- Function whose return result is used as the message for display as above. If it throws an exception, the exception message is displayed. The algorithm is effectively:
Default:try{ var message = opts.run(); this.status (message, opts.successClass, opts); }catch(ex){ this.status (ex.message, opts.failureClass, opts); }
$.noop
. - As of version 1.1, the
run
function can return aPromise
, with success or failure defined as resolution or rejection of thatPromise
, as:
(whererun().then (function(message){ this.status (message, opts.successClass, opts); }, function(ex){ this.status (ex.message, opts.failureClass, opts); });
this
really means the jQuery object. Arrow notation and lexicalthis
would be nice!) prompt
{String|false
}- If not
false
(the test is===false
), then therun
function expects a string as a parameter (themessage
line above would bevar message = opts.run(text);
. A text input box is appended to the element with something like$('<label>').text(opts.prompt).appendTo(this).append('<input>');
(see below for the actual markup). It is displayed withopts.show
. When the user hits "enter" the text in the input box is passed to theopts.run
function as above. If the user hits "esc" thenopts.cancelMessage
is displayed without runningopts.run
. In either case, the input box is hidden withopts.hide
. - A simple history is implemented; the up arrow will display the previous string entered or
"undefined"
if there is no previous string. - Default
false
. initialText
{Boolean | String}- Only relevant if
prompt
istrue
. If a string, use it as the initial value of the input element. Iftrue
then useprompt
as a placeholder rather than a separate element. iffalse
,prompt
is outside the input element as above, and the input element itself is blank. cancelMessage
{String}- The message to display if "esc" is hit in the input box. Default
'User Canceled'
. returnPromise
{Boolean}- Internally, the code uses a
Promise
, so the actual algorithm is closer to:
Setvar promise = new Promise(function(resolve){ resolve(opts.run()); }); promise.then( function(message){ this.status (message, opts.successClass, opts); }, function(ex){ this.status (ex.message, opts.failureClass, opts); });
returnPromise
totrue
to return thatPromise
rather thanthis
. This plugin uses that for signalling rather than events. Default:false
.
So a sample "Save As" to the server would be:
function saveas(name){
return $.post('save.php', {name: name, text: $('#editor').val()}).then(
function() { return name + ' saved' },
function() { return new Error(name + ' not saved') })
}
$('#notification').status({
prompt: 'Save As:',
run: saveas
});
Note that jQuery $.Deferred
s like $.post
aren't real Promise
s but implement then()
, so the Promise
code can handle it.
Multiple elements
jQuery objects can contain zero or more elements. run
will run exactly once, no matter how many elements are in the object (or even if there are none) and the output message will be displayed in each of them. Input (if the prompt
option is set) will be taken from the first element in the jQuery object, or if it is empty, via window.prompt
. Note that window.prompt
is synchronous and will block the rest of the page until it is addressed. However, it is pumped through a Promise
, so from the point of view of code execution it is asynchronous (is executed on the next tick).
$(console).status()
jQuery will happily wrap non-DOM elements, which allows me to use the console rather than an element on the page for messages. $(console).status(...)
will work exactly as above, but messages are printed with console.log()
and errors with console.error()
. Input is with window.prompt
as above (I can't figure out any way to get input from the console.
Under the hood, it just calls log()
and error()
, so you can create your own output mechanism:
var output = {
log: function (text) { alert (text) },
error: function (text) { alert ('Error: '+text) },
prompt: function (promptText, initialText) { window.prompt(promptText, initialText) }
};
$(output).status({run: saveFunction});
For input, when the target is not a real DOM node, the plugin will call target-object.prompt (prompt, initialText)
if it exists; otherwise it will use window.prompt
. The target-object.prompt
function can return a string for a result or null
for cancel, the way window.prompt
does, or it can return a Promise
that resolves to the result string. For example, you could use jQuery UI dialogs (see the dialog
object in the demo)
Markup
It would be nice, with prompted input, for the input line to fill the available space. That is possible, if the markup is in the right order, with the input element last in the containing element. That means that all messages, even ones that should appear after the input element, and float
ed to the right side.
So messages (that do not require user input) are prepended to the parent element, with markup
<span class=classname>Message Text</span>
and your stylesheet should include
span.classname {
float: right;
}
The input element itself is appended to the parent element, and marked up as
<label><strong>Prompt</strong><span><input/></span></label>
And CSS should be
label strong {
/* the prompt itself */
float: left;
}
label span {
/* wrapper for the input element */
float: none;
display: block;
overflow: hidden;
}
label input {
width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
Hacking at 0300 : Input elements that fill the available space says:
[…] my status plugin, I'd generally like the input element to take up the whole line, or at least the part that's not […]
January 9, 2014, 10:23 am