Skip to content

Commit

Permalink
add support for short form button keys, restrict wrapper methods to a…
Browse files Browse the repository at this point in the history
…ppropriate buttons
  • Loading branch information
makeusabrew committed Aug 26, 2013
1 parent 62aee59 commit 01b0180
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 21 deletions.
50 changes: 43 additions & 7 deletions bootbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,22 @@ window.bootbox = window.bootbox || (function init($, undefined) {

each(buttons, function(key, button, index) {

// @TODO it wold be so easy here to use key as the button label if
// not supplied, and also check if button was a function to support
// a nice condensed label -> callback style
if ($.isFunction(button)) {
// short form, assume value is our callback. Since button
// isn't an object it isn't a reference either so re-assign it
button = buttons[key] = {
callback: button
};
}

// before any further checks make sure by now button is the correct type
if ($.type(button) !== "object") {
throw new Error("button with key " + key + " must be an object");
}

if (!button.label) {
throw new Error("button with key " + key + " requires a label");
// the lack of an explicit label means we'll assume the key is good enough
button.label = key;
}

if (!button.className) {
Expand Down Expand Up @@ -167,6 +178,13 @@ window.bootbox = window.bootbox || (function init($, undefined) {
return $.extend(true, {}, defaults, mapArguments(args, properties));
}

function mergeButtons(labels, args, properties) {
return validateButtons(
mergeArguments(createButtons.apply(null, labels), args, properties),
labels
);
}

function createLabels() {
var buttons = {};

Expand All @@ -189,10 +207,25 @@ window.bootbox = window.bootbox || (function init($, undefined) {
};
}

function validateButtons(options, buttons) {
var allowedButtons = {};
each(buttons, function(key, value) {
allowedButtons[value] = true;
});

each(options.buttons, function(key) {
if (allowedButtons[key] === undefined) {
throw new Error("button key " + key + " is not allowed (options are " + buttons.join("\n") + ")");
}
});

return options;
}

exports.alert = function() {
var options;

options = mergeArguments(createButtons("ok"), arguments, ["message", "callback"]);
options = mergeButtons(["ok"], arguments, ["message", "callback"]);

if (options.callback && !$.isFunction(options.callback)) {
throw new Error("alert requires callback property to be a function when provided");
Expand All @@ -214,7 +247,7 @@ window.bootbox = window.bootbox || (function init($, undefined) {
exports.confirm = function() {
var options;

options = mergeArguments(createButtons("cancel", "confirm"), arguments, ["message", "callback"]);
options = mergeButtons(["cancel", "confirm"], arguments, ["message", "callback"]);

/**
* overrides; undo anything the user tried to set they shouldn't have
Expand Down Expand Up @@ -254,7 +287,10 @@ window.bootbox = window.bootbox || (function init($, undefined) {
value: ""
};

options = mergeArguments(defaults, arguments, ["title", "callback"]);
options = validateButtons(
mergeArguments(defaults, arguments, ["title", "callback"]),
["cancel", "confirm"]
);

// capture the user's show value; we always set this to false before
// spawning the dialog to give us a chance to attach some handlers to
Expand Down
15 changes: 15 additions & 0 deletions tests/alert.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,21 @@ describe("bootbox.alert", function() {
});
});

describe("with an unrecognised button key", function() {
beforeEach(function() {
this.options.buttons = {
"Another key": {
label: "Custom OK",
className: "btn-danger"
}
};
});

it("throws an error", function() {
expect(this.create).to.throw("button key Another key is not allowed (options are ok)");
});
});

describe("with a custom title", function() {
beforeEach(function() {
this.options.title = "Hello?";
Expand Down
10 changes: 10 additions & 0 deletions tests/confirm.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ describe "bootbox.confirm", ->
expect(@button.text()).to.equal "Custom confirm"
expect(@button.hasClass("btn-warning")).to.be.true

describe "with an unrecognised button key", ->
beforeEach ->
@options.buttons =
"Bad key":
label: "Custom confirm"
className: "btn-warning"

it "throws an error", ->
expect(@create).to.throw /key is not allowed/

describe "callback tests", ->
describe "with a simple callback", ->
beforeEach ->
Expand Down
57 changes: 48 additions & 9 deletions tests/dialog.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,16 @@ describe "bootbox.dialog", ->
it "throws an error", ->
expect(@create).to.throw /specify a message/

describe "where the argument has a button with no label", ->
describe "where the argument has a button with an invalid value", ->
beforeEach ->
@create = ->
bootbox.dialog
message: "test"
buttons:
ok:
callback: -> true
ok: "foo"

it "throws an error", ->
expect(@create).to.throw /button with key ok requires a label/
expect(@create).to.throw /button with key ok must be an object/

describe "when creating a minimal dialog", ->
beforeEach ->
Expand Down Expand Up @@ -89,11 +88,6 @@ describe "bootbox.dialog", ->
buttons:
one: button

describe "when the button has no label", ->

it "throws an error", ->
expect(@create).to.throw /button with key one requires a label/

describe "when the button has no callback", ->
beforeEach ->
@create
Expand Down Expand Up @@ -185,6 +179,51 @@ describe "bootbox.dialog", ->
it "adds the custom class to the button", ->
expect(@class(".btn", "btn-custom")).to.be.true

describe "when the button has no explicit label", ->
beforeEach ->
@create = (buttons) ->
@dialog = bootbox.dialog
message: "test"
buttons: buttons

describe "when its value is an object", ->
beforeEach ->
@create
"Short form":
className: "btn-custom"
callback: -> true

it "uses the key name as the button text", ->
expect(@text(".btn")).to.equal "Short form"

it "adds the custom class to the button", ->
expect(@class(".btn", "btn-custom")).to.be.true

describe "when its value is a function", ->
beforeEach ->
@callback = sinon.spy()
@create
my_label: @callback

it "uses the key name as the button text", ->
expect(@text(".btn")).to.equal "my_label"

describe "when dismissing the dialog by clicking the button", ->
beforeEach ->
@dialog.find(".btn-primary").trigger "click"

it "should invoke the callback", ->
expect(@callback).to.have.been.called

describe "when its value is not an object or function", ->
beforeEach ->
@badCreate = =>
@create
"Short form": "hello world"

it "throws an error", ->
expect(@badCreate).to.throw /button with key Short form must be an object/

describe "when creating a dialog with a title", ->
beforeEach ->
@dialog = bootbox.dialog
Expand Down
20 changes: 15 additions & 5 deletions tests/prompt.test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -128,21 +128,31 @@ describe "bootbox.prompt", ->
expect(@button.text()).to.equal "Custom cancel"
expect(@button.hasClass("btn-danger")).to.be.true

describe "with a custom prompt button", ->
describe "with a custom confirm button", ->
beforeEach ->
@options.buttons =
prompt:
label: "Custom prompt"
confirm:
label: "Custom confirm"
className: "btn-warning"

@create()

@button = @dialog.find(".btn:last")

it "adds the correct prompt button", ->
expect(@button.text()).to.equal "Custom prompt"
it "adds the correct confirm button", ->
expect(@button.text()).to.equal "Custom confirm"
expect(@button.hasClass("btn-warning")).to.be.true

describe "with an unrecognised button key", ->
beforeEach ->
@options.buttons =
prompt:
label: "Custom confirm"
className: "btn-warning"

it "throws an error", ->
expect(@create).to.throw /key prompt is not allowed/

describe "setting show to false", ->
beforeEach ->
@options.show = false
Expand Down

0 comments on commit 01b0180

Please sign in to comment.