[Pkg-javascript-commits] [libjs-bootbox] 01/02: Import Upstream version 4.4.0+dfsg1
Johannes Schauer
josch at moszumanska.debian.org
Wed Jul 5 18:03:22 UTC 2017
This is an automated email from the git hooks/post-receive script.
josch pushed a commit to branch master
in repository libjs-bootbox.
commit ae544f9c63aeb974b26b09dc313416458582c6f1
Author: Johannes Schauer <josch at debian.org>
Date: Wed Jul 5 20:02:46 2017 +0200
Import Upstream version 4.4.0+dfsg1
---
.gitignore | 9 +
.jshintrc | 24 +
.npmignore | 8 +
.travis.yml | 3 +
CHANGELOG.md | 186 ++++++
CONTRIBUTING.md | 17 +
Gruntfile.js | 33 ++
LICENSE.md | 23 +
README.md | 91 +++
bootbox.js | 985 ++++++++++++++++++++++++++++++++
bower.json | 17 +
build/calculate-size | 14 +
header.txt | 5 +
karma-base.conf.js | 51 ++
karma-jquery-latest.conf.js | 8 +
karma.conf.js | 8 +
package.json | 35 ++
tests/alert.test.js | 355 ++++++++++++
tests/bootbox.test.js | 269 +++++++++
tests/confirm.test.coffee | 260 +++++++++
tests/defaults.test.js | 186 ++++++
tests/dialog.test.coffee | 349 ++++++++++++
tests/locales.test.coffee | 378 +++++++++++++
tests/prompt.test.coffee | 1306 +++++++++++++++++++++++++++++++++++++++++++
24 files changed, 4620 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1132214
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+*.swo
+*.swp
+node_modules
+npm-debug.log
+bootbox.min.js
+.idea
+tests/reports
+tests/coverage
+build/size.csv
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000..1a88199
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,24 @@
+{
+ "undef": true,
+ "unused": true,
+ "eqeqeq": true,
+ "curly": true,
+ "newcap": true,
+ "strict": true,
+ "trailing": true,
+ "quotmark": "double",
+ "browser": true,
+
+ "globals": {
+ "beforeEach": true,
+ "afterEach": true,
+ "describe": true,
+ "it": true,
+ "define": true,
+ "module": true,
+ "require": true,
+ "expect": true,
+ "bootbox": true,
+ "sinon": true
+ }
+}
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..ec7f091
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,8 @@
+*.swo
+*.swp
+node_modules
+npm-debug.log
+.idea
+tests/reports
+tests/coverage
+build/size.csv
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..6e5919d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "0.10"
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..76f62fa
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,186 @@
+### Latest Release: 4.4.0
+
+* Allow `backdrop` options of `true` and `false` to dismiss modals
+* Pass dialog as `this` value in callbacks
+* Bootstrap 3.3.2 compatibility
+* jQuery 1.11.2 compatibility
+* Add support for `maxlength` prompt input attribute
+* Gracefully detect lack of Bootstrap library rather than crashing
+* Expose `addLocale` and `removeLocale` for custom locale settings
+* Expose `setLocale` helper to select a locale rather than using `setDefaults("locale", ...)`
+* Add Hungarian locale
+* Add Croatian locale
+* Add Bulgarian locale
+* Add Thai locale
+* Add Persian locale
+* Add Albanian locale
+
+## 4.3.0
+
+* Add `size` option (large, small)
+* Stop propagation on form submit
+* Return bootbox object from `hideAll`
+* Add Portuguese locale
+* Add Czech locale
+* Add Greek locale
+* Add Estonian locale
+* Add Indonesian locale
+* Add Japanese locale
+
+### 4.2.0
+
+* Add Swedish locale
+* Add Latvian locale
+* Add Turkish locale
+* Add Hebrew locale
+* Add password input type
+* Add textarea input type
+* Add date input type
+* Add time input type
+* Add number input type
+* Support DOM selectors for container argument
+* UMD support
+* Better support on mobile devices
+
+### 4.1.0
+
+* Add support for placeholder attribute in prompts
+* Add select, email and checkbox types for prompts (thanks [@tarlepp](https://github.com/tarlepp))
+* Add Norwegian locale
+* Allow setDefaults to take two key/val arguments
+* Add unique classes for main dialog methods
+* Create bower package
+
+### 4.0.0
+
+* Bootstrap 3.0.0 compatibility
+* Complete rewrite (and new public API)
+* Use strict mode
+* Add close buttons to wrapper methods (GH-92)
+* Allow dialog titles to be specified (GH-51, GH-112)
+* Allow optional extra class on dialog wrapper (GH-116)
+* Fix ```backdrop: true``` not firing close handler (GH-77)
+* Replace various configuration methods with one ```setDefaults```
+
+### 3.3.0
+
+* Add Polish translation (GH-93)
+* Add Danish translation (GH-96)
+* Pass event object to custom callbacks (GH-103)
+* Add Chinese (Taiwan / China) translations (GH-106)
+* Make prompt input block-level (GH-111)
+* Add link: true option to prevent btn class from being applied (GH-114)
+* Prevent child elements triggering hidden callback (GH-115)
+* Replace Phing with Grunt
+* Replace Closure compiler with UglifyJS
+
+### 3.2.0
+
+* ensure ```onEscape``` handlers return callback values properly (GH-91)
+* ensure clicking close button invokes onEscape handler if present
+
+### 3.1.0
+
+* ensure ```confirm``` and ```prompt``` methods return callback values properly (GH-90)
+* address various jshint warnings (GH-79)
+* add ```setBtnClasses``` method for custom standard button classes (GH-87)
+
+### 3.0.0
+
+* bump Bootstrap dependency to 2.2.2
+* bump jQuery dependency to 1.8.3
+* ensure callbacks are always invoked even if dialogs are dismissed with escape key (GH-49)
+* fix button positions with Bootstrap 2.2.2 (GH-58)
+* stop multiple dialogs crashing browsers (GH-60, GH-64)
+* ensure ```shown``` event is fired properly even when animation is disabled (GH-69)
+* use ```.on``` instead of ```.bind```
+* commentify code a bit more
+
+### 2.5.1
+
+**This was the last version of the library to support Bootstrap 2.0.x**
+
+* ensure bootbox object is explicitly added to window object for minfier visibility
+
+### 2.5.0
+
+* add option to specify proper href attributes for buttons instead of callbacks (@StevePotter)
+* add option to override per-modal classes (@ciaranj)
+
+### 2.4.2
+
+* revert ```backdrop``` default value to 'static' instead of ```true``` to prevent background clicks dismissing dialogs (GH-55)
+
+### 2.4.1
+
+* fix ```backdrop``` when supplied as an argument to ```bootbox.dialog```
+* fix incorrect README version
+
+### 2.4.0
+
+* add ```bootbox.backdrop(bool)``` method (@gucki)
+* add default parameter option to ```bootbox.prompt``` (@pzgz)
+
+### 2.3.3
+
+* add inline ```overflow: hidden``` CSS property (GH-46)
+* move license info to separate hosted file to reduce file size
+
+### 2.3.2
+
+* Change button href attributes to ```javascript:;``` (@joshnesbitt)
+* Explicitly ```window.jQuery``` through to ```Bootbox``` object (@nuegon)
+
+
+### 2.3.1
+
+* Ensure bootbox.prompt() gives focus to input, disable input autocomplete
+
+### 2.3.0
+
+* Added bootbox.prompt() to mimic native prompt() method
+* Added Russian locale (#27)
+
+### 2.2.0
+
+* Allowed button callbacks to explicitly return false to prevent dialog from closing (thanks @benoit-ponsero)
+* Added version number to header comments (#26)
+
+### 2.1.2
+
+* Added close button to re-scoped click handler (thanks @SeanMcGee and @kentbrew)
+
+### 2.1.1
+
+* Fixed incorrect button click handler selector (thanks FGRibreau)
+
+### 2.1.0
+
+* Added support for Bootstrap's Glyphicons via the ```icon``` option
+* Added inline license information into bootbox.js and bootbox.min.js
+* Tidied up source a little
+
+### 2.0.1
+
+* Removed dummy Google Closure Compiler method from minified library (thanks j0k3r!)
+
+### 2.0.0
+
+* Updated Bootstrap dependency from 1.4 to 2.0
+* Class definitions now require ```btn-``` prefix as per Bootstrap 2.0
+* Added Brazilian locale
+* Added ```animate``` dialog option
+* Added ```bootbox.animate(bool)``` option to set default animation preference
+* Animated dialogs now rely on ```bootstrap-transitions.js``` as required by Bootstrap 2.0
+
+### 1.1.2
+
+* Added licensing information to README
+
+#### 1.1.1
+* Updated german locale
+
+#### 1.1.0
+* Secondary option of two-button dialog no longer has 'danger' class
+* New bootbox.modal() method for generic non-dialog popups
+* Allow jQuery objects to be passed as main dialog argument
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..0ba843c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,17 @@
+## Submitting Pull Requests
+
+**Please follow these basic steps to simplify pull request reviews - if you don't you'll probably just be asked to anyway.**
+
+* Please rebase your branch against the current master
+* Run ```npm install``` to make sure your development dependencies are up-to-date
+* [grunt-cli](https://github.com/gruntjs/grunt-cli) >= 0.4.0 is required to sanity check your contribution
+* Please ensure that the test suite passes **and** that bootbox.js is lint free before submitting a PR by running:
+ * ```grunt```
+* If you've added new functionality, **please** include tests which validate its behaviour
+ * **this includes pull requests which _only_ add new locales!**
+
+## Submitting bug reports
+
+* Where at all possible, please try and provide a link to a jsfiddle.net example or similar
+* Please detail the affected browser(s) and operating system(s)
+* Please be sure to state which version of Bootbox, jQuery **and** Bootstrap you're using
diff --git a/Gruntfile.js b/Gruntfile.js
new file mode 100644
index 0000000..cc059ed
--- /dev/null
+++ b/Gruntfile.js
@@ -0,0 +1,33 @@
+module.exports = function(grunt) {
+ grunt.initConfig({
+ uglify: {
+ options: {
+ banner: grunt.file.read("header.txt")
+ },
+ build: {
+ files: {
+ "bootbox.min.js": ["bootbox.js"]
+ }
+ }
+ },
+
+ jshint: {
+ options: {
+ jshintrc: ".jshintrc"
+ },
+ all: ["bootbox.js"]
+ },
+
+ karma: {
+ unit: {
+ configFile: "karma.conf.js"
+ }
+ }
+ });
+
+ grunt.loadNpmTasks("grunt-contrib-uglify");
+ grunt.loadNpmTasks("grunt-contrib-jshint");
+ grunt.loadNpmTasks("grunt-karma");
+
+ grunt.registerTask("default", ["jshint", "karma"]);
+};
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..8219f59
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,23 @@
+# License
+
+(The MIT License)
+
+Copyright (C) 2011-2014 by Nick Payne <nick at kurai.co.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..55bf55f
--- /dev/null
+++ b/README.md
@@ -0,0 +1,91 @@
+# Bootbox - Bootstrap powered alert, confirm and flexible dialog boxes
+
+Please see http://bootboxjs.com for full usage instructions, or head over to http://paynedigital.com/bootbox for
+the original writeup about the project.
+
+## Contact
+
+The easiest thing is to [find me on twitter @makeusabrew](http://twitter.com/makeusabrew).
+
+## Contributing
+
+Please see the [CONTRIBUTING](https://github.com/makeusabrew/bootbox/blob/master/CONTRIBUTING.md) file for guidelines.
+
+## Running Tests [![Build Status](https://api.travis-ci.org/makeusabrew/bootbox.svg)](http://travis-ci.org/makeusabrew/bootbox)
+
+Tests are run using [Karma](http://karma-runner.github.io/0.8/index.html) using the Mocha test adapter.
+To run the tests yourself, simply run ```npm install``` within the project followed by ```npm test```.
+Please note that this will require [PhantomJS](http://phantomjs.org/) being installed and in your path - if
+it is not, you may run the tests and capture browsers manually by running ```karma start``` from the root
+of the project.
+
+The project is also hosted on [Travis CI](https://travis-ci.org/makeusabrew/bootbox) - when submitting
+pull requests **please** ensure your tests pass as failing requests will be rejected. See the
+[CONTRIBUTING](https://github.com/makeusabrew/bootbox/blob/master/CONTRIBUTING.md) file for more information.
+
+## Building a minified release
+
+The repository no longer contains a minified bootbox.min.js file - this is now only generated
+[for releases](https://github.com/makeusabrew/bootbox/releases). To build your own minified copy
+for use in development simply run ```npm install``` if you haven't already, followed by ```grunt uglify```.
+This will generate a bootbox.min.js file in your working directory.
+
+## A note on Bootstrap dependencies
+
+Bootbox **4.0.0** is the first release to support Bootstrap 3.0.0.
+
+Bootbox **3.3.0** is the *last* release to support Bootstrap 2.2.x.
+
+Much more dependency information can be found [on the Bootbox website](http://bootboxjs.com/#dependencies).
+
+### Roadmap
+
+The latest major release of Bootbox - 4.0.0 - involved a total rewrite of the
+internal code and introduced an entirely new public API. It has not re-implemented
+some functionality from the 3.x series as of yet; this will be addressed in the
+the form of new minor releases. Please feel free to add feedback and requests.
+
+There is no new major (e.g. 5.x) release on the roadmap at present.
+
+### Latest Release: 4.4.0
+
+* Allow `backdrop` options of `true` and `false` to dismiss modals
+* Pass dialog as `this` value in callbacks
+* Bootstrap 3.3.2 compatibility
+* jQuery 1.11.2 compatibility
+* Add support for `maxlength` prompt input attribute
+* Gracefully detect lack of Bootstrap library rather than crashing
+* Expose `addLocale` and `removeLocale` for custom locale settings
+* Expose `setLocale` helper to select a locale rather than using `setDefaults("locale", ...)`
+* Add Hungarian locale
+* Add Croatian locale
+* Add Bulgarian locale
+* Add Thai locale
+* Add Persian locale
+* Add Albanian locale
+
+For a full list of releases and changes please see [the changelog](https://github.com/makeusabrew/bootbox/blob/master/CHANGELOG.md).
+
+## License
+
+(The MIT License)
+
+Copyright (C) 2011-2015 by Nick Payne <nick at kurai.co.uk>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE
diff --git a/bootbox.js b/bootbox.js
new file mode 100644
index 0000000..3e8312a
--- /dev/null
+++ b/bootbox.js
@@ -0,0 +1,985 @@
+/**
+ * bootbox.js [v4.4.0]
+ *
+ * http://bootboxjs.com/license.txt
+ */
+
+// @see https://github.com/makeusabrew/bootbox/issues/180
+// @see https://github.com/makeusabrew/bootbox/issues/186
+(function (root, factory) {
+
+ "use strict";
+ if (typeof define === "function" && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(["jquery"], factory);
+ } else if (typeof exports === "object") {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like environments that support module.exports,
+ // like Node.
+ module.exports = factory(require("jquery"));
+ } else {
+ // Browser globals (root is window)
+ root.bootbox = factory(root.jQuery);
+ }
+
+}(this, function init($, undefined) {
+
+ "use strict";
+
+ // the base DOM structure needed to create a modal
+ var templates = {
+ dialog:
+ "<div class='bootbox modal' tabindex='-1' role='dialog'>" +
+ "<div class='modal-dialog'>" +
+ "<div class='modal-content'>" +
+ "<div class='modal-body'><div class='bootbox-body'></div></div>" +
+ "</div>" +
+ "</div>" +
+ "</div>",
+ header:
+ "<div class='modal-header'>" +
+ "<h4 class='modal-title'></h4>" +
+ "</div>",
+ footer:
+ "<div class='modal-footer'></div>",
+ closeButton:
+ "<button type='button' class='bootbox-close-button close' data-dismiss='modal' aria-hidden='true'>×</button>",
+ form:
+ "<form class='bootbox-form'></form>",
+ inputs: {
+ text:
+ "<input class='bootbox-input bootbox-input-text form-control' autocomplete=off type=text />",
+ textarea:
+ "<textarea class='bootbox-input bootbox-input-textarea form-control'></textarea>",
+ email:
+ "<input class='bootbox-input bootbox-input-email form-control' autocomplete='off' type='email' />",
+ select:
+ "<select class='bootbox-input bootbox-input-select form-control'></select>",
+ checkbox:
+ "<div class='checkbox'><label><input class='bootbox-input bootbox-input-checkbox' type='checkbox' /></label></div>",
+ date:
+ "<input class='bootbox-input bootbox-input-date form-control' autocomplete=off type='date' />",
+ time:
+ "<input class='bootbox-input bootbox-input-time form-control' autocomplete=off type='time' />",
+ number:
+ "<input class='bootbox-input bootbox-input-number form-control' autocomplete=off type='number' />",
+ password:
+ "<input class='bootbox-input bootbox-input-password form-control' autocomplete='off' type='password' />"
+ }
+ };
+
+ var defaults = {
+ // default language
+ locale: "en",
+ // show backdrop or not. Default to static so user has to interact with dialog
+ backdrop: "static",
+ // animate the modal in/out
+ animate: true,
+ // additional class string applied to the top level dialog
+ className: null,
+ // whether or not to include a close button
+ closeButton: true,
+ // show the dialog immediately by default
+ show: true,
+ // dialog container
+ container: "body"
+ };
+
+ // our public object; augmented after our private API
+ var exports = {};
+
+ /**
+ * @private
+ */
+ function _t(key) {
+ var locale = locales[defaults.locale];
+ return locale ? locale[key] : locales.en[key];
+ }
+
+ function processCallback(e, dialog, callback) {
+ e.stopPropagation();
+ e.preventDefault();
+
+ // by default we assume a callback will get rid of the dialog,
+ // although it is given the opportunity to override this
+
+ // so, if the callback can be invoked and it *explicitly returns false*
+ // then we'll set a flag to keep the dialog active...
+ var preserveDialog = $.isFunction(callback) && callback.call(dialog, e) === false;
+
+ // ... otherwise we'll bin it
+ if (!preserveDialog) {
+ dialog.modal("hide");
+ }
+ }
+
+ function getKeyLength(obj) {
+ // @TODO defer to Object.keys(x).length if available?
+ var k, t = 0;
+ for (k in obj) {
+ t ++;
+ }
+ return t;
+ }
+
+ function each(collection, iterator) {
+ var index = 0;
+ $.each(collection, function(key, value) {
+ iterator(key, value, index++);
+ });
+ }
+
+ function sanitize(options) {
+ var buttons;
+ var total;
+
+ if (typeof options !== "object") {
+ throw new Error("Please supply an object of options");
+ }
+
+ if (!options.message) {
+ throw new Error("Please specify a message");
+ }
+
+ // make sure any supplied options take precedence over defaults
+ options = $.extend({}, defaults, options);
+
+ if (!options.buttons) {
+ options.buttons = {};
+ }
+
+ buttons = options.buttons;
+
+ total = getKeyLength(buttons);
+
+ each(buttons, function(key, button, index) {
+
+ 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) {
+ // the lack of an explicit label means we'll assume the key is good enough
+ button.label = key;
+ }
+
+ if (!button.className) {
+ if (total <= 2 && index === total-1) {
+ // always add a primary to the main option in a two-button dialog
+ button.className = "btn-primary";
+ } else {
+ button.className = "btn-default";
+ }
+ }
+ });
+
+ return options;
+ }
+
+ /**
+ * map a flexible set of arguments into a single returned object
+ * if args.length is already one just return it, otherwise
+ * use the properties argument to map the unnamed args to
+ * object properties
+ * so in the latter case:
+ * mapArguments(["foo", $.noop], ["message", "callback"])
+ * -> { message: "foo", callback: $.noop }
+ */
+ function mapArguments(args, properties) {
+ var argn = args.length;
+ var options = {};
+
+ if (argn < 1 || argn > 2) {
+ throw new Error("Invalid argument length");
+ }
+
+ if (argn === 2 || typeof args[0] === "string") {
+ options[properties[0]] = args[0];
+ options[properties[1]] = args[1];
+ } else {
+ options = args[0];
+ }
+
+ return options;
+ }
+
+ /**
+ * merge a set of default dialog options with user supplied arguments
+ */
+ function mergeArguments(defaults, args, properties) {
+ return $.extend(
+ // deep merge
+ true,
+ // ensure the target is an empty, unreferenced object
+ {},
+ // the base options object for this type of dialog (often just buttons)
+ defaults,
+ // args could be an object or array; if it's an array properties will
+ // map it to a proper options object
+ mapArguments(
+ args,
+ properties
+ )
+ );
+ }
+
+ /**
+ * this entry-level method makes heavy use of composition to take a simple
+ * range of inputs and return valid options suitable for passing to bootbox.dialog
+ */
+ function mergeDialogOptions(className, labels, properties, args) {
+ // build up a base set of dialog properties
+ var baseOptions = {
+ className: "bootbox-" + className,
+ buttons: createLabels.apply(null, labels)
+ };
+
+ // ensure the buttons properties generated, *after* merging
+ // with user args are still valid against the supplied labels
+ return validateButtons(
+ // merge the generated base properties with user supplied arguments
+ mergeArguments(
+ baseOptions,
+ args,
+ // if args.length > 1, properties specify how each arg maps to an object key
+ properties
+ ),
+ labels
+ );
+ }
+
+ /**
+ * from a given list of arguments return a suitable object of button labels
+ * all this does is normalise the given labels and translate them where possible
+ * e.g. "ok", "confirm" -> { ok: "OK, cancel: "Annuleren" }
+ */
+ function createLabels() {
+ var buttons = {};
+
+ for (var i = 0, j = arguments.length; i < j; i++) {
+ var argument = arguments[i];
+ var key = argument.toLowerCase();
+ var value = argument.toUpperCase();
+
+ buttons[key] = {
+ label: _t(value)
+ };
+ }
+
+ return buttons;
+ }
+
+ 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 = mergeDialogOptions("alert", ["ok"], ["message", "callback"], arguments);
+
+ if (options.callback && !$.isFunction(options.callback)) {
+ throw new Error("alert requires callback property to be a function when provided");
+ }
+
+ /**
+ * overrides
+ */
+ options.buttons.ok.callback = options.onEscape = function() {
+ if ($.isFunction(options.callback)) {
+ return options.callback.call(this);
+ }
+ return true;
+ };
+
+ return exports.dialog(options);
+ };
+
+ exports.confirm = function() {
+ var options;
+
+ options = mergeDialogOptions("confirm", ["cancel", "confirm"], ["message", "callback"], arguments);
+
+ /**
+ * overrides; undo anything the user tried to set they shouldn't have
+ */
+ options.buttons.cancel.callback = options.onEscape = function() {
+ return options.callback.call(this, false);
+ };
+
+ options.buttons.confirm.callback = function() {
+ return options.callback.call(this, true);
+ };
+
+ // confirm specific validation
+ if (!$.isFunction(options.callback)) {
+ throw new Error("confirm requires a callback");
+ }
+
+ return exports.dialog(options);
+ };
+
+ exports.prompt = function() {
+ var options;
+ var defaults;
+ var dialog;
+ var form;
+ var input;
+ var shouldShow;
+ var inputOptions;
+
+ // we have to create our form first otherwise
+ // its value is undefined when gearing up our options
+ // @TODO this could be solved by allowing message to
+ // be a function instead...
+ form = $(templates.form);
+
+ // prompt defaults are more complex than others in that
+ // users can override more defaults
+ // @TODO I don't like that prompt has to do a lot of heavy
+ // lifting which mergeDialogOptions can *almost* support already
+ // just because of 'value' and 'inputType' - can we refactor?
+ defaults = {
+ className: "bootbox-prompt",
+ buttons: createLabels("cancel", "confirm"),
+ value: "",
+ inputType: "text"
+ };
+
+ 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
+ // it, but we need to make sure we respect a preference not to show it
+ shouldShow = (options.show === undefined) ? true : options.show;
+
+ /**
+ * overrides; undo anything the user tried to set they shouldn't have
+ */
+ options.message = form;
+
+ options.buttons.cancel.callback = options.onEscape = function() {
+ return options.callback.call(this, null);
+ };
+
+ options.buttons.confirm.callback = function() {
+ var value;
+
+ switch (options.inputType) {
+ case "text":
+ case "textarea":
+ case "email":
+ case "select":
+ case "date":
+ case "time":
+ case "number":
+ case "password":
+ value = input.val();
+ break;
+
+ case "checkbox":
+ var checkedItems = input.find("input:checked");
+
+ // we assume that checkboxes are always multiple,
+ // hence we default to an empty array
+ value = [];
+
+ each(checkedItems, function(_, item) {
+ value.push($(item).val());
+ });
+ break;
+ }
+
+ return options.callback.call(this, value);
+ };
+
+ options.show = false;
+
+ // prompt specific validation
+ if (!options.title) {
+ throw new Error("prompt requires a title");
+ }
+
+ if (!$.isFunction(options.callback)) {
+ throw new Error("prompt requires a callback");
+ }
+
+ if (!templates.inputs[options.inputType]) {
+ throw new Error("invalid prompt type");
+ }
+
+ // create the input based on the supplied type
+ input = $(templates.inputs[options.inputType]);
+
+ switch (options.inputType) {
+ case "text":
+ case "textarea":
+ case "email":
+ case "date":
+ case "time":
+ case "number":
+ case "password":
+ input.val(options.value);
+ break;
+
+ case "select":
+ var groups = {};
+ inputOptions = options.inputOptions || [];
+
+ if (!$.isArray(inputOptions)) {
+ throw new Error("Please pass an array of input options");
+ }
+
+ if (!inputOptions.length) {
+ throw new Error("prompt with select requires options");
+ }
+
+ each(inputOptions, function(_, option) {
+
+ // assume the element to attach to is the input...
+ var elem = input;
+
+ if (option.value === undefined || option.text === undefined) {
+ throw new Error("given options in wrong format");
+ }
+
+ // ... but override that element if this option sits in a group
+
+ if (option.group) {
+ // initialise group if necessary
+ if (!groups[option.group]) {
+ groups[option.group] = $("<optgroup/>").attr("label", option.group);
+ }
+
+ elem = groups[option.group];
+ }
+
+ elem.append("<option value='" + option.value + "'>" + option.text + "</option>");
+ });
+
+ each(groups, function(_, group) {
+ input.append(group);
+ });
+
+ // safe to set a select's value as per a normal input
+ input.val(options.value);
+ break;
+
+ case "checkbox":
+ var values = $.isArray(options.value) ? options.value : [options.value];
+ inputOptions = options.inputOptions || [];
+
+ if (!inputOptions.length) {
+ throw new Error("prompt with checkbox requires options");
+ }
+
+ if (!inputOptions[0].value || !inputOptions[0].text) {
+ throw new Error("given options in wrong format");
+ }
+
+ // checkboxes have to nest within a containing element, so
+ // they break the rules a bit and we end up re-assigning
+ // our 'input' element to this container instead
+ input = $("<div/>");
+
+ each(inputOptions, function(_, option) {
+ var checkbox = $(templates.inputs[options.inputType]);
+
+ checkbox.find("input").attr("value", option.value);
+ checkbox.find("label").append(option.text);
+
+ // we've ensured values is an array so we can always iterate over it
+ each(values, function(_, value) {
+ if (value === option.value) {
+ checkbox.find("input").prop("checked", true);
+ }
+ });
+
+ input.append(checkbox);
+ });
+ break;
+ }
+
+ // @TODO provide an attributes option instead
+ // and simply map that as keys: vals
+ if (options.placeholder) {
+ input.attr("placeholder", options.placeholder);
+ }
+
+ if (options.pattern) {
+ input.attr("pattern", options.pattern);
+ }
+
+ if (options.maxlength) {
+ input.attr("maxlength", options.maxlength);
+ }
+
+ // now place it in our form
+ form.append(input);
+
+ form.on("submit", function(e) {
+ e.preventDefault();
+ // Fix for SammyJS (or similar JS routing library) hijacking the form post.
+ e.stopPropagation();
+ // @TODO can we actually click *the* button object instead?
+ // e.g. buttons.confirm.click() or similar
+ dialog.find(".btn-primary").click();
+ });
+
+ dialog = exports.dialog(options);
+
+ // clear the existing handler focusing the submit button...
+ dialog.off("shown.bs.modal");
+
+ // ...and replace it with one focusing our input, if possible
+ dialog.on("shown.bs.modal", function() {
+ // need the closure here since input isn't
+ // an object otherwise
+ input.focus();
+ });
+
+ if (shouldShow === true) {
+ dialog.modal("show");
+ }
+
+ return dialog;
+ };
+
+ exports.dialog = function(options) {
+ options = sanitize(options);
+
+ var dialog = $(templates.dialog);
+ var innerDialog = dialog.find(".modal-dialog");
+ var body = dialog.find(".modal-body");
+ var buttons = options.buttons;
+ var buttonStr = "";
+ var callbacks = {
+ onEscape: options.onEscape
+ };
+
+ if ($.fn.modal === undefined) {
+ throw new Error(
+ "$.fn.modal is not defined; please double check you have included " +
+ "the Bootstrap JavaScript library. See http://getbootstrap.com/javascript/ " +
+ "for more details."
+ );
+ }
+
+ each(buttons, function(key, button) {
+
+ // @TODO I don't like this string appending to itself; bit dirty. Needs reworking
+ // can we just build up button elements instead? slower but neater. Then button
+ // can just become a template too
+ buttonStr += "<button data-bb-handler='" + key + "' type='button' class='btn " + button.className + "'>" + button.label + "</button>";
+ callbacks[key] = button.callback;
+ });
+
+ body.find(".bootbox-body").html(options.message);
+
+ if (options.animate === true) {
+ dialog.addClass("fade");
+ }
+
+ if (options.className) {
+ dialog.addClass(options.className);
+ }
+
+ if (options.size === "large") {
+ innerDialog.addClass("modal-lg");
+ } else if (options.size === "small") {
+ innerDialog.addClass("modal-sm");
+ }
+
+ if (options.title) {
+ body.before(templates.header);
+ }
+
+ if (options.closeButton) {
+ var closeButton = $(templates.closeButton);
+
+ if (options.title) {
+ dialog.find(".modal-header").prepend(closeButton);
+ } else {
+ closeButton.css("margin-top", "-10px").prependTo(body);
+ }
+ }
+
+ if (options.title) {
+ dialog.find(".modal-title").html(options.title);
+ }
+
+ if (buttonStr.length) {
+ body.after(templates.footer);
+ dialog.find(".modal-footer").html(buttonStr);
+ }
+
+
+ /**
+ * Bootstrap event listeners; used handle extra
+ * setup & teardown required after the underlying
+ * modal has performed certain actions
+ */
+
+ dialog.on("hidden.bs.modal", function(e) {
+ // ensure we don't accidentally intercept hidden events triggered
+ // by children of the current dialog. We shouldn't anymore now BS
+ // namespaces its events; but still worth doing
+ if (e.target === this) {
+ dialog.remove();
+ }
+ });
+
+ /*
+ dialog.on("show.bs.modal", function() {
+ // sadly this doesn't work; show is called *just* before
+ // the backdrop is added so we'd need a setTimeout hack or
+ // otherwise... leaving in as would be nice
+ if (options.backdrop) {
+ dialog.next(".modal-backdrop").addClass("bootbox-backdrop");
+ }
+ });
+ */
+
+ dialog.on("shown.bs.modal", function() {
+ dialog.find(".btn-primary:first").focus();
+ });
+
+ /**
+ * Bootbox event listeners; experimental and may not last
+ * just an attempt to decouple some behaviours from their
+ * respective triggers
+ */
+
+ if (options.backdrop !== "static") {
+ // A boolean true/false according to the Bootstrap docs
+ // should show a dialog the user can dismiss by clicking on
+ // the background.
+ // We always only ever pass static/false to the actual
+ // $.modal function because with `true` we can't trap
+ // this event (the .modal-backdrop swallows it)
+ // However, we still want to sort of respect true
+ // and invoke the escape mechanism instead
+ dialog.on("click.dismiss.bs.modal", function(e) {
+ // @NOTE: the target varies in >= 3.3.x releases since the modal backdrop
+ // moved *inside* the outer dialog rather than *alongside* it
+ if (dialog.children(".modal-backdrop").length) {
+ e.currentTarget = dialog.children(".modal-backdrop").get(0);
+ }
+
+ if (e.target !== e.currentTarget) {
+ return;
+ }
+
+ dialog.trigger("escape.close.bb");
+ });
+ }
+
+ dialog.on("escape.close.bb", function(e) {
+ if (callbacks.onEscape) {
+ processCallback(e, dialog, callbacks.onEscape);
+ }
+ });
+
+ /**
+ * Standard jQuery event listeners; used to handle user
+ * interaction with our dialog
+ */
+
+ dialog.on("click", ".modal-footer button", function(e) {
+ var callbackKey = $(this).data("bb-handler");
+
+ processCallback(e, dialog, callbacks[callbackKey]);
+ });
+
+ dialog.on("click", ".bootbox-close-button", function(e) {
+ // onEscape might be falsy but that's fine; the fact is
+ // if the user has managed to click the close button we
+ // have to close the dialog, callback or not
+ processCallback(e, dialog, callbacks.onEscape);
+ });
+
+ dialog.on("keyup", function(e) {
+ if (e.which === 27) {
+ dialog.trigger("escape.close.bb");
+ }
+ });
+
+ // the remainder of this method simply deals with adding our
+ // dialogent to the DOM, augmenting it with Bootstrap's modal
+ // functionality and then giving the resulting object back
+ // to our caller
+
+ $(options.container).append(dialog);
+
+ dialog.modal({
+ backdrop: options.backdrop ? "static": false,
+ keyboard: false,
+ show: false
+ });
+
+ if (options.show) {
+ dialog.modal("show");
+ }
+
+ // @TODO should we return the raw element here or should
+ // we wrap it in an object on which we can expose some neater
+ // methods, e.g. var d = bootbox.alert(); d.hide(); instead
+ // of d.modal("hide");
+
+ /*
+ function BBDialog(elem) {
+ this.elem = elem;
+ }
+
+ BBDialog.prototype = {
+ hide: function() {
+ return this.elem.modal("hide");
+ },
+ show: function() {
+ return this.elem.modal("show");
+ }
+ };
+ */
+
+ return dialog;
+
+ };
+
+ exports.setDefaults = function() {
+ var values = {};
+
+ if (arguments.length === 2) {
+ // allow passing of single key/value...
+ values[arguments[0]] = arguments[1];
+ } else {
+ // ... and as an object too
+ values = arguments[0];
+ }
+
+ $.extend(defaults, values);
+ };
+
+ exports.hideAll = function() {
+ $(".bootbox").modal("hide");
+
+ return exports;
+ };
+
+
+ /**
+ * standard locales. Please add more according to ISO 639-1 standard. Multiple language variants are
+ * unlikely to be required. If this gets too large it can be split out into separate JS files.
+ */
+ var locales = {
+ bg_BG : {
+ OK : "Ок",
+ CANCEL : "Отказ",
+ CONFIRM : "Потвърждавам"
+ },
+ br : {
+ OK : "OK",
+ CANCEL : "Cancelar",
+ CONFIRM : "Sim"
+ },
+ cs : {
+ OK : "OK",
+ CANCEL : "Zrušit",
+ CONFIRM : "Potvrdit"
+ },
+ da : {
+ OK : "OK",
+ CANCEL : "Annuller",
+ CONFIRM : "Accepter"
+ },
+ de : {
+ OK : "OK",
+ CANCEL : "Abbrechen",
+ CONFIRM : "Akzeptieren"
+ },
+ el : {
+ OK : "Εντάξει",
+ CANCEL : "Ακύρωση",
+ CONFIRM : "Επιβεβαίωση"
+ },
+ en : {
+ OK : "OK",
+ CANCEL : "Cancel",
+ CONFIRM : "OK"
+ },
+ es : {
+ OK : "OK",
+ CANCEL : "Cancelar",
+ CONFIRM : "Aceptar"
+ },
+ et : {
+ OK : "OK",
+ CANCEL : "Katkesta",
+ CONFIRM : "OK"
+ },
+ fa : {
+ OK : "قبول",
+ CANCEL : "لغو",
+ CONFIRM : "تایید"
+ },
+ fi : {
+ OK : "OK",
+ CANCEL : "Peruuta",
+ CONFIRM : "OK"
+ },
+ fr : {
+ OK : "OK",
+ CANCEL : "Annuler",
+ CONFIRM : "D'accord"
+ },
+ he : {
+ OK : "אישור",
+ CANCEL : "ביטול",
+ CONFIRM : "אישור"
+ },
+ hu : {
+ OK : "OK",
+ CANCEL : "Mégsem",
+ CONFIRM : "Megerősít"
+ },
+ hr : {
+ OK : "OK",
+ CANCEL : "Odustani",
+ CONFIRM : "Potvrdi"
+ },
+ id : {
+ OK : "OK",
+ CANCEL : "Batal",
+ CONFIRM : "OK"
+ },
+ it : {
+ OK : "OK",
+ CANCEL : "Annulla",
+ CONFIRM : "Conferma"
+ },
+ ja : {
+ OK : "OK",
+ CANCEL : "キャンセル",
+ CONFIRM : "確認"
+ },
+ lt : {
+ OK : "Gerai",
+ CANCEL : "Atšaukti",
+ CONFIRM : "Patvirtinti"
+ },
+ lv : {
+ OK : "Labi",
+ CANCEL : "Atcelt",
+ CONFIRM : "Apstiprināt"
+ },
+ nl : {
+ OK : "OK",
+ CANCEL : "Annuleren",
+ CONFIRM : "Accepteren"
+ },
+ no : {
+ OK : "OK",
+ CANCEL : "Avbryt",
+ CONFIRM : "OK"
+ },
+ pl : {
+ OK : "OK",
+ CANCEL : "Anuluj",
+ CONFIRM : "Potwierdź"
+ },
+ pt : {
+ OK : "OK",
+ CANCEL : "Cancelar",
+ CONFIRM : "Confirmar"
+ },
+ ru : {
+ OK : "OK",
+ CANCEL : "Отмена",
+ CONFIRM : "Применить"
+ },
+ sq : {
+ OK : "OK",
+ CANCEL : "Anulo",
+ CONFIRM : "Prano"
+ },
+ sv : {
+ OK : "OK",
+ CANCEL : "Avbryt",
+ CONFIRM : "OK"
+ },
+ th : {
+ OK : "ตกลง",
+ CANCEL : "ยกเลิก",
+ CONFIRM : "ยืนยัน"
+ },
+ tr : {
+ OK : "Tamam",
+ CANCEL : "İptal",
+ CONFIRM : "Onayla"
+ },
+ zh_CN : {
+ OK : "OK",
+ CANCEL : "取消",
+ CONFIRM : "确认"
+ },
+ zh_TW : {
+ OK : "OK",
+ CANCEL : "取消",
+ CONFIRM : "確認"
+ }
+ };
+
+ exports.addLocale = function(name, values) {
+ $.each(["OK", "CANCEL", "CONFIRM"], function(_, v) {
+ if (!values[v]) {
+ throw new Error("Please supply a translation for '" + v + "'");
+ }
+ });
+
+ locales[name] = {
+ OK: values.OK,
+ CANCEL: values.CANCEL,
+ CONFIRM: values.CONFIRM
+ };
+
+ return exports;
+ };
+
+ exports.removeLocale = function(name) {
+ delete locales[name];
+
+ return exports;
+ };
+
+ exports.setLocale = function(name) {
+ return exports.setDefaults("locale", name);
+ };
+
+ exports.init = function(_$) {
+ return init(_$ || $);
+ };
+
+ return exports;
+}));
diff --git a/bower.json b/bower.json
new file mode 100644
index 0000000..87e1ef5
--- /dev/null
+++ b/bower.json
@@ -0,0 +1,17 @@
+{
+ "name": "bootbox.js",
+ "version": "4.4.0",
+ "main": "./bootbox.js",
+ "ignore": [
+ "CHANGELOG.md",
+ "CONTRIBUTING",
+ "Gruntfile.js",
+ "header.txt",
+ "karma*.js",
+ "build",
+ "tests"
+ ],
+ "dependencies": {
+ "bootstrap": ">= 3.0.0"
+ }
+}
diff --git a/build/calculate-size b/build/calculate-size
new file mode 100755
index 0000000..fbc0555
--- /dev/null
+++ b/build/calculate-size
@@ -0,0 +1,14 @@
+#!/usr/bin/env zsh
+
+SRC="bootbox.js"
+MIN="/tmp/bootbox.min.js"
+
+uglifyjs $SRC -c -m > $MIN
+
+RAW="$(wc -c $SRC | awk '{print $1}')"
+MRAW="$(wc -c $MIN | awk '{print $1}')"
+GZIP="$(cat $SRC | gzip | wc -c | awk '{print $1}')"
+MGZIP="$(cat $MIN | gzip | wc -c | awk '{print $1}')"
+
+echo "raw,min,raw+gzip,min+gzip\n$RAW,$MRAW,$GZIP,$MGZIP" > build/size.csv
+rm $MIN
diff --git a/header.txt b/header.txt
new file mode 100644
index 0000000..2778b0d
--- /dev/null
+++ b/header.txt
@@ -0,0 +1,5 @@
+/**
+ * bootbox.js v4.4.0
+ *
+ * http://bootboxjs.com/license.txt
+ */
diff --git a/karma-base.conf.js b/karma-base.conf.js
new file mode 100644
index 0000000..6dc52a3
--- /dev/null
+++ b/karma-base.conf.js
@@ -0,0 +1,51 @@
+module.exports = function(params) {
+
+ "use strict";
+
+ console.log("Vendor files: " + params.vendor.join(", "));
+
+ return function(config) {
+
+ return config.set({
+ basePath: "",
+ frameworks: ["mocha", "chai"],
+ files: Array.prototype.concat([
+ "node_modules/sinon/lib/sinon.js",
+ "node_modules/sinon/lib/sinon/spy.js",
+ "node_modules/sinon/lib/sinon/stub.js",
+ "node_modules/sinon-chai/lib/sinon-chai.js"],
+
+ params.vendor,
+
+ params.src || "bootbox.js",
+
+ ["tests/**/*.test.coffee",
+ "tests/**/*.test.js"]
+ ),
+ exclude: [],
+ preprocessors: {
+ "**/*.coffee": ["coffee"],
+ "bootbox.js": ["coverage"]
+ },
+ reporters: ["dots", "coverage", "junit"],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: ["PhantomJS"],
+ captureTimeout: 60000,
+ singleRun: true,
+
+ coverageReporter: {
+ type: "html",
+ dir: "tests/coverage"
+ },
+
+ junitReporter: {
+ outputFile: "tests/reports/results.xml"
+ }
+ });
+
+ };
+
+};
diff --git a/karma-jquery-latest.conf.js b/karma-jquery-latest.conf.js
new file mode 100644
index 0000000..094d3e5
--- /dev/null
+++ b/karma-jquery-latest.conf.js
@@ -0,0 +1,8 @@
+var baseConfig = require("./karma-base.conf");
+
+module.exports = baseConfig({
+ vendor: [
+ "tests/vendor/jquery-1.10.2.min.js",
+ "tests/vendor/bootstrap-3.0.0.min.js"
+ ]
+});
diff --git a/karma.conf.js b/karma.conf.js
new file mode 100644
index 0000000..5d1f9f3
--- /dev/null
+++ b/karma.conf.js
@@ -0,0 +1,8 @@
+var baseConfig = require("./karma-base.conf");
+
+module.exports = baseConfig({
+ vendor: [
+ "tests/vendor/jquery-1.11.2.min.js",
+ "tests/vendor/bootstrap-3.3.2.min.js"
+ ]
+});
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..3b71016
--- /dev/null
+++ b/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "bootbox",
+ "version": "4.4.0",
+ "description": "Wrappers for JavaScript alert(), confirm() and other flexible dialogs using the Bootstrap framework",
+ "directories": {
+ "test": "tests"
+ },
+ "scripts": {
+ "test": "./node_modules/.bin/karma start"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/makeusabrew/bootbox.git"
+ },
+ "author": "Nick Payne <nick at kurai.co.uk>",
+ "license": "MIT",
+ "readmeFilename": "README.md",
+ "main": "bootbox.js",
+ "devDependencies": {
+ "grunt-contrib-uglify": "~0.2.2",
+ "grunt": "~0.4.1",
+ "karma": "~0.10.1",
+ "grunt-contrib-jshint": "~0.6.3",
+ "karma-mocha": "0.1.3",
+ "karma-phantomjs-launcher": "~0.1.0",
+ "mocha": "~1.12.0",
+ "karma-coffee-preprocessor": "~0.1.0",
+ "karma-coverage": "~0.1.0",
+ "karma-junit-reporter": "~0.1.0",
+ "sinon": "~1.7.3",
+ "sinon-chai": "~2.4.0",
+ "karma-chai": "0.0.1",
+ "grunt-karma": "~0.6.2"
+ }
+}
diff --git a/tests/alert.test.js b/tests/alert.test.js
new file mode 100644
index 0000000..bc441a5
--- /dev/null
+++ b/tests/alert.test.js
@@ -0,0 +1,355 @@
+describe("bootbox.alert", function() {
+
+ "use strict";
+
+ var self;
+
+ beforeEach(function() {
+
+ self = this;
+
+ this.text = function(selector) {
+ return this.find(selector).text();
+ };
+
+ this.find = function(selector) {
+ return this.dialog.find(selector);
+ };
+ });
+
+ describe("basic usage tests", function() {
+
+ describe("with no arguments", function() {
+ beforeEach(function() {
+ this.create = function() {
+ bootbox.alert();
+ };
+ });
+
+ it("throws an error regarding argument length", function() {
+ expect(this.create).to.throw(/argument length/);
+ });
+ });
+
+ describe("with one argument", function() {
+
+ describe("where the argument is a string", function() {
+ beforeEach(function() {
+ this.dialog = bootbox.alert("Hello world!");
+ });
+
+ it("applies the bootbox-alert class to the dialog", function() {
+ expect(this.dialog.hasClass("bootbox-alert")).to.be.true;
+ });
+
+ it("shows the expected body copy", function() {
+ expect(this.text(".bootbox-body")).to.equal("Hello world!");
+ });
+
+ it("shows an OK button", function() {
+ expect(this.text(".modal-footer button:first")).to.equal("OK");
+ });
+
+ it("applies the primary class to the button", function() {
+ expect(this.find(".modal-footer button:first").hasClass("btn-primary")).to.be.true;
+ });
+
+ it("shows a close button inside the body", function() {
+ expect(this.text(".modal-body button")).to.equal("×");
+ });
+
+ it("applies the close class to the close button", function() {
+ expect(this.find(".modal-body button").hasClass("close")).to.be.true;
+ });
+
+ it("applies the correct data-dismiss attribute to the close button", function() {
+ expect(this.find("button.close").attr("data-dismiss")).to.equal("modal");
+ });
+
+ it("applies the correct aria-hidden attribute to the close button", function() {
+ expect(this.find("button.close").attr("aria-hidden")).to.equal("true");
+ });
+
+ it("applies the correct class to the body", function() {
+ expect($("body").hasClass("modal-open")).to.be.true;
+ });
+ });
+ });
+
+ describe("with two arguments", function() {
+ describe("where the second argument is not a function", function() {
+ beforeEach(function() {
+ this.create = function() {
+ bootbox.alert("Hello world!", "not a callback");
+ };
+ });
+
+ it("throws an error requiring a callback", function() {
+ expect(this.create).to.throw(/alert requires callback property to be a function when provided/);
+ });
+ });
+
+ describe("where the second argument is a function", function() {
+ beforeEach(function() {
+ this.create = function() {
+ self.dialog = bootbox.alert("Hello world!", function() {});
+ };
+ });
+
+ it("does not throw an error", function() {
+ expect(this.create).not.to.throw(Error);
+ });
+ });
+ });
+
+ describe("with three arguments", function() {
+ beforeEach(function() {
+ this.create = function() {
+ bootbox.alert(1, 2, 3);
+ };
+ });
+
+ it("throws an error regarding argument length", function() {
+ expect(this.create).to.throw(/argument length/);
+ });
+ });
+
+ });
+
+ describe("configuration options tests", function() {
+ beforeEach(function() {
+ this.options = {
+ message: "Hello world",
+ callback: function() {}
+ };
+
+ this.create = function() {
+ self.dialog = bootbox.alert(self.options);
+ };
+ });
+
+ describe("with a custom ok button", function() {
+ beforeEach(function() {
+ this.options.buttons = {
+ ok: {
+ label: "Custom OK",
+ className: "btn-danger"
+ }
+ };
+
+ this.create();
+
+ this.button = this.dialog.find(".btn:first");
+ });
+
+ it("adds the correct ok button", function() {
+ expect(this.button.text()).to.equal("Custom OK");
+ expect(this.button.hasClass("btn-danger")).to.be.true;
+ });
+ });
+
+ 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?";
+ this.create();
+ });
+
+ it("shows the correct title", function() {
+ expect(this.text("h4")).to.equal("Hello?");
+ });
+ });
+ });
+
+ describe("callback tests", function() {
+
+ describe("with no callback", function() {
+ beforeEach(function() {
+ this.dialog = bootbox.alert({
+ message:"Hello!"
+ });
+
+ this.hidden = sinon.spy(this.dialog, "modal");
+ });
+
+ describe("when dismissing the dialog by clicking OK", function() {
+ beforeEach(function() {
+ this.dialog.find(".btn-primary").trigger("click");
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+
+ describe("when clicking the close button", function() {
+ beforeEach(function() {
+ this.dialog.find(".close").trigger("click");
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+
+ describe("when triggering the escape event", function() {
+ beforeEach(function() {
+ this.dialog.trigger("escape.close.bb");
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+ });
+
+ describe("with a simple callback", function() {
+ beforeEach(function() {
+ this.callback = sinon.spy();
+
+ this.dialog = bootbox.alert({
+ message:"Hello!",
+ callback: this.callback
+ });
+
+ this.hidden = sinon.spy(this.dialog, "modal");
+ });
+
+ describe("when dismissing the dialog by clicking OK", function() {
+ beforeEach(function() {
+ this.dialog.find(".btn-primary").trigger("click");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+
+ describe("when clicking the close button", function() {
+ beforeEach(function() {
+ this.dialog.find(".close").trigger("click");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+
+ describe("when triggering the escape event", function() {
+ beforeEach(function() {
+ this.dialog.trigger("escape.close.bb");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should hide the modal", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+ });
+
+ describe("with a callback which returns false", function() {
+ beforeEach(function() {
+ this.callback = sinon.stub();
+ this.callback.returns(false);
+
+ this.dialog = bootbox.alert({
+ message:"Hello!",
+ callback: this.callback
+ });
+
+ this.hidden = sinon.spy(this.dialog, "modal");
+ });
+
+ describe("when dismissing the dialog by clicking OK", function() {
+ beforeEach(function() {
+ this.dialog.find(".btn-primary").trigger("click");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should not hide the modal", function() {
+ expect(this.hidden).not.to.have.been.called;
+ });
+ });
+
+ describe("when clicking the close button", function() {
+ beforeEach(function() {
+ this.dialog.find(".close").trigger("click");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should not hide the modal", function() {
+ expect(this.hidden).not.to.have.been.called;
+ });
+ });
+
+ describe("when triggering the escape event", function() {
+ beforeEach(function() {
+ this.dialog.trigger("escape.close.bb");
+ });
+
+ it("should invoke the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+
+ it("should not hide the modal", function() {
+ expect(this.hidden).not.to.have.been.called;
+ });
+ });
+ });
+ });
+});
diff --git a/tests/bootbox.test.js b/tests/bootbox.test.js
new file mode 100644
index 0000000..2700224
--- /dev/null
+++ b/tests/bootbox.test.js
@@ -0,0 +1,269 @@
+describe("Bootbox", function() {
+
+ "use strict";
+
+ it("is attached to the window object", function() {
+ expect(window.bootbox).to.be.an("object");
+ });
+
+ it("exposes the correct public API", function() {
+ expect(bootbox.alert).to.be.a("function");
+ expect(bootbox.confirm).to.be.a("function");
+ expect(bootbox.dialog).to.be.a("function");
+ expect(bootbox.setDefaults).to.be.a("function");
+ expect(bootbox.hideAll).to.be.a("function");
+ });
+
+ describe("hideAll", function() {
+ beforeEach(function() {
+ this.hidden = sinon.spy($.fn, "modal");
+ bootbox.hideAll();
+ });
+
+ it("should hide all .bootbox modals", function() {
+ expect(this.hidden).to.have.been.calledWithExactly("hide");
+ });
+ });
+
+ describe("event listeners", function() {
+ describe("hidden.bs.modal", function() {
+ beforeEach(function() {
+ this.dialog = bootbox.alert("hi");
+
+ this.removed = sinon.stub(this.dialog, "remove");
+
+ this.e = function(target) {
+
+ $(this.dialog).trigger($.Event("hidden.bs.modal", {
+ target: target
+ }));
+ };
+ });
+
+ afterEach(function() {
+ this.removed.restore();
+ });
+
+ describe("when triggered with the wrong target", function() {
+ beforeEach(function() {
+ this.e({an: "object"});
+ });
+
+ it("does not remove the dialog", function() {
+ expect(this.removed).not.to.have.been.called;
+ });
+ });
+
+ describe("when triggered with the correct target", function() {
+ beforeEach(function() {
+ this.e(this.dialog.get(0));
+ });
+
+ it("removes the dialog", function() {
+ expect(this.removed).to.have.been.called;
+ });
+ });
+ });
+ });
+
+ describe("If $.fn.modal is undefined", function() {
+ beforeEach(function() {
+ this.oldModal = window.jQuery.fn.modal;
+ window.jQuery.fn.modal = undefined;
+ });
+
+ afterEach(function() {
+ window.jQuery.fn.modal = this.oldModal;
+ });
+
+ describe("When invoking a dialog", function() {
+ beforeEach(function() {
+ try {
+ bootbox.alert("Hi", function() {});
+ } catch (e) {
+ this.e = e;
+ }
+ });
+
+ it("throws the correct error", function() {
+ expect(this.e.message).to.contain("$.fn.modal is not defined");
+ });
+ });
+ });
+
+ describe("adding and removing locales", function() {
+
+ describe("bootbox.addLocale", function() {
+ describe("with invalid values", function() {
+ beforeEach(function() {
+ try {
+ bootbox.addLocale("xy", {
+ OK: "BTN1"
+ });
+ } catch (e) {
+ this.e = e;
+ }
+ });
+
+ it("throws the expected error", function() {
+ expect(this.e.message).to.equal("Please supply a translation for 'CANCEL'");
+ });
+ });
+
+ describe("with invalid values", function() {
+ beforeEach(function() {
+ bootbox
+ .addLocale("xy", {
+ OK: "BTN1",
+ CANCEL: "BTN2",
+ CONFIRM: "BTN3"
+ })
+ .setLocale("xy");
+
+ var d1 = bootbox.alert("foo");
+ var d2 = bootbox.confirm("foo", function() { return true; });
+ this.labels = {
+ ok: d1.find(".btn:first").text(),
+ cancel: d2.find(".btn:first").text(),
+ confirm: d2.find(".btn:last").text()
+ };
+ });
+
+ it("shows the expected OK translation", function() {
+ expect(this.labels.ok).to.equal("BTN1");
+ });
+ it("shows the expected CANCEL translation", function() {
+ expect(this.labels.cancel).to.equal("BTN2");
+ });
+ it("shows the expected PROMPT translation", function() {
+ expect(this.labels.confirm).to.equal("BTN3");
+ });
+ });
+ });
+
+ describe("bootbox.removeLocale", function () {
+ beforeEach(function () {
+ bootbox.removeLocale("xy");
+
+ var d1 = bootbox.alert("foo");
+ var d2 = bootbox.confirm("foo", function () { return true; });
+ this.labels = {
+ ok: d1.find(".btn:first").text(),
+ cancel: d2.find(".btn:first").text(),
+ confirm: d2.find(".btn:last").text()
+ };
+ });
+
+ it("falls back to the default OK translation", function () {
+ expect(this.labels.ok).to.equal("OK");
+ });
+ it("falls back to the default CANCEL translation", function () {
+ expect(this.labels.cancel).to.equal("Cancel");
+ });
+ it("falls back to the default PROMPT translation", function () {
+ expect(this.labels.confirm).to.equal("OK");
+ });
+ });
+ });
+
+ describe("backdrop variations", function() {
+ beforeEach(function() {
+ this.e = function(target) {
+ $(this.dialog).trigger($.Event("click.dismiss.bs.modal", {
+ target: target
+ }));
+ };
+ });
+
+ describe("with the default value", function() {
+ beforeEach(function() {
+ this.callback = sinon.spy();
+ this.dialog = bootbox.alert("hi", this.callback);
+ });
+
+ describe("When triggering the backdrop click dismiss event", function() {
+ beforeEach(function() {
+ this.e({an: "object"});
+ });
+
+ it("does not invoke the callback", function() {
+ expect(this.callback).not.to.have.been.called;
+ });
+ });
+ });
+
+ describe("when set to false", function() {
+ beforeEach(function() {
+ this.callback = sinon.spy();
+ this.dialog = bootbox.alert({
+ message: "hi",
+ callback: this.callback,
+ backdrop: false
+ });
+ });
+
+ describe("When triggering the backdrop click dismiss event", function() {
+ describe("With the wrong target", function() {
+ beforeEach(function() {
+ this.e({an: "object"});
+ });
+
+ it("does not invoke the callback", function() {
+ expect(this.callback).not.to.have.been.called;
+ });
+ });
+
+ describe("With the correct target", function() {
+ beforeEach(function() {
+ this.e(this.dialog.get(0));
+ });
+
+ it("invokes the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+ });
+ });
+ });
+
+ describe("when set to true", function() {
+ beforeEach(function() {
+ this.callback = sinon.spy();
+ this.dialog = bootbox.alert({
+ message: "hi",
+ callback: this.callback,
+ backdrop: true
+ });
+ });
+
+ describe("When triggering the backdrop click dismiss event", function() {
+ describe("With the wrong target", function() {
+ beforeEach(function() {
+ this.e({an: "object"});
+ });
+
+ it("does not invoke the callback", function() {
+ expect(this.callback).not.to.have.been.called;
+ });
+ });
+
+ describe("With the correct target", function() {
+ beforeEach(function() {
+ this.e(this.dialog.children(".modal-backdrop").get(0));
+ });
+
+ it("invokes the callback", function() {
+ expect(this.callback).to.have.been.called;
+ });
+
+ it("should pass the dialog as `this`", function() {
+ expect(this.callback.thisValues[0]).to.equal(this.dialog);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/tests/confirm.test.coffee b/tests/confirm.test.coffee
new file mode 100644
index 0000000..fd7d06a
--- /dev/null
+++ b/tests/confirm.test.coffee
@@ -0,0 +1,260 @@
+describe "bootbox.confirm", ->
+
+ describe "basic usage tests", ->
+
+ describe "with one argument", ->
+
+ describe "where the argument is not an object", ->
+ beforeEach ->
+ @create = -> bootbox.confirm "Are you sure?"
+
+ it "throws an error", ->
+ expect(@create).to.throw /confirm requires a callback/
+
+ describe "where the argument is an object", ->
+ beforeEach ->
+ @options = {}
+ @create = => @dialog = bootbox.confirm @options
+
+ describe "with a message property", ->
+ beforeEach ->
+ @options.message = "Are you sure?"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /confirm requires a callback/
+
+ describe "with a callback property", ->
+ describe "where the callback is not a function", ->
+ beforeEach ->
+ @options.callback = "Are you sure?"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /confirm requires a callback/
+
+ describe "where the callback is a function", ->
+ beforeEach ->
+ @options.callback = -> true
+
+ it "throws an error requiring a message", ->
+ expect(@create).to.throw /Please specify a message/
+
+ describe "with a message and a callback", ->
+ beforeEach ->
+ @options =
+ callback: -> true
+ message: "Are you sure?"
+
+ it "does not throw an error", ->
+ expect(@create).not.to.throw Error
+
+ it "creates a dialog object", ->
+ expect(@dialog).to.be.an "object"
+
+ it "adds the correct button labels", ->
+ expect(@dialog.find(".btn:first").text()).to.equal "Cancel"
+ expect(@dialog.find(".btn:last").text()).to.equal "OK"
+
+ it "adds the correct button classes", ->
+ expect(@dialog.find(".btn:first").hasClass("btn-default")).to.be.true
+ expect(@dialog.find(".btn:last").hasClass("btn-primary")).to.be.true
+
+ describe "with two arguments", ->
+ describe "where the second argument is not a function", ->
+ beforeEach ->
+ @create = =>
+ @dialog = bootbox.confirm "Are you sure?", "callback here"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /confirm requires a callback/
+
+ describe "where the second argument is a function", ->
+ beforeEach ->
+ @create = =>
+ @dialog = bootbox.confirm "Are you sure?", -> true
+
+ it "does not throw an error", ->
+ expect(@create).not.to.throw Error
+
+ it "creates a dialog object", ->
+ expect(@dialog).to.be.an "object"
+
+ it "applies the bootbox-confirm class to the dialog", ->
+ expect(@dialog.hasClass("bootbox-confirm")).to.be.true
+
+ it "adds the correct button labels", ->
+ expect(@dialog.find(".btn:first").text()).to.equal "Cancel"
+ expect(@dialog.find(".btn:last").text()).to.equal "OK"
+
+ it "adds the correct button classes", ->
+ expect(@dialog.find(".btn:first").hasClass("btn-default")).to.be.true
+ expect(@dialog.find(".btn:last").hasClass("btn-primary")).to.be.true
+
+ it "shows the dialog", ->
+ expect(@dialog.is(":visible")).to.be.true
+
+ describe "configuration options tests", ->
+ beforeEach ->
+ @options =
+ message: "Are you sure?"
+ callback: -> true
+
+ @create = =>
+ @dialog = bootbox.confirm @options
+
+ describe "with a custom cancel button", ->
+ beforeEach ->
+ @options.buttons =
+ cancel:
+ label: "Custom cancel"
+ className: "btn-danger"
+
+ @create()
+
+ @button = @dialog.find(".btn:first")
+
+ it "adds the correct cancel button", ->
+ expect(@button.text()).to.equal "Custom cancel"
+ expect(@button.hasClass("btn-danger")).to.be.true
+
+ describe "with a custom confirm button", ->
+ beforeEach ->
+ @options.buttons =
+ confirm:
+ label: "Custom confirm"
+ className: "btn-warning"
+
+ @create()
+
+ @button = @dialog.find(".btn:last")
+
+ 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 =
+ "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 ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.confirm
+ message: "Are you sure?"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly true
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly false
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly false
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "with a callback which returns false", ->
+ beforeEach ->
+ @callback = sinon.stub()
+ @callback.returns false
+
+ @dialog = bootbox.confirm
+ message: "Are you sure?"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly true
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly false
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly false
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
diff --git a/tests/defaults.test.js b/tests/defaults.test.js
new file mode 100644
index 0000000..89fe717
--- /dev/null
+++ b/tests/defaults.test.js
@@ -0,0 +1,186 @@
+describe("bootbox.setDefaults", function() {
+
+ beforeEach(function() {
+ this.find = function(selector) {
+ return this.dialog.find(selector);
+ };
+ });
+
+ describe("animate", function() {
+ describe("when set to false", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ animate: false
+ });
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("does not add the fade class to the dialog", function() {
+ expect(this.dialog.hasClass("fade")).to.be.false;
+ });
+
+ it("applies the correct class to the body", function() {
+ expect($("body").hasClass("modal-open")).to.be.true;
+ });
+
+ describe("when clicking the close button", function() {
+ beforeEach(function() {
+ this.dialog.find(".close").trigger("click");
+ });
+
+ it("removes the modal-open class from the body", function() {
+ expect($("body").hasClass("modal-open")).to.be.false;
+ });
+ });
+ });
+
+ describe("when set to true", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ animate: true
+ });
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("adds the fade class to the dialog", function() {
+ expect(this.dialog.hasClass("fade")).to.be.true;
+ });
+ });
+ });
+
+ describe("className", function() {
+ describe("when passed as a string", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ className: "my-class"
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("adds the extra class to the outer dialog", function() {
+ expect(this.dialog.hasClass("bootbox")).to.be.true;
+ expect(this.dialog.hasClass("my-class")).to.be.true;
+ });
+ });
+ });
+
+ describe("size", function() {
+ describe("when set to large", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ size: "large"
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("adds the large class to the innerDialog", function() {
+ expect(this.dialog.children(".modal-dialog").hasClass("modal-lg")).to.be.true;
+ });
+ });
+ describe("when set to small", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ size: "small"
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("adds the small class to the innerDialog", function() {
+ expect(this.dialog.children(".modal-dialog").hasClass("modal-sm")).to.be.true;
+ });
+ });
+ });
+
+ describe("backdrop", function() {
+ describe("when set to false", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ backdrop: false
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("does not show a backdrop", function() {
+ expect(this.dialog.next(".modal-backdrop").length).to.equal(0);
+ });
+ });
+ });
+
+ describe("when passed two arguments", function() {
+ beforeEach(function() {
+ bootbox.setDefaults("className", "my-class");
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("applies the arguments as a key/value pair", function() {
+ expect(this.dialog.hasClass("bootbox")).to.be.true;
+ expect(this.dialog.hasClass("my-class")).to.be.true;
+ });
+ });
+
+ describe("container", function () {
+ describe("when not explicitly set", function() {
+ beforeEach(function() {
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("defaults to the body element", function() {
+ expect(this.dialog.parent().is("body")).to.be.true;
+ });
+ });
+
+ describe("when explicitly set to body", function() {
+ beforeEach(function() {
+ bootbox.setDefaults({
+ container: "body"
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("sets the correct parent element", function() {
+ expect(this.dialog.parent().is("body")).to.be.true;
+ });
+ });
+
+ describe("when set to another dom element", function() {
+
+ beforeEach(function() {
+ this.container = $("<div></div>");
+ bootbox.setDefaults({
+ container: this.container
+ });
+
+ this.dialog = bootbox.dialog({
+ message: "test"
+ });
+ });
+
+ it("sets the correct parent element", function() {
+ expect(this.dialog.parent().is(this.container)).to.be.true;
+ });
+ });
+ });
+});
diff --git a/tests/dialog.test.coffee b/tests/dialog.test.coffee
new file mode 100644
index 0000000..5c7000d
--- /dev/null
+++ b/tests/dialog.test.coffee
@@ -0,0 +1,349 @@
+describe "bootbox.dialog", ->
+ beforeEach ->
+
+ # need to take care with these helpers; don't want too much
+ # cleverness in the tests which runs the risk of making them
+ # harder to read. Could we look at custom expectations instead?
+ @find = (s) -> @dialog.find s
+ @exists = (s) -> @find(s).length isnt 0
+ @class = (s, c) -> @find(s).hasClass(c)
+ @invoke = (s, m) -> @find(s)[m]()
+ @text = (s) -> @invoke s, "text"
+ @html = (s) -> @invoke s, "html"
+
+ describe "invalid usage tests", ->
+
+ describe "with no arguments", ->
+
+ beforeEach ->
+ @create = -> bootbox.dialog()
+
+ it "throws an error", ->
+ expect(@create).to.throw /supply an object/
+
+ describe "with one argument", ->
+
+ describe "where the argument is not an object", ->
+ beforeEach ->
+ @create = -> bootbox.dialog "test"
+
+ it "throws an error", ->
+ expect(@create).to.throw /supply an object/
+
+ describe "where the argument has no message property", ->
+ beforeEach ->
+ @create = ->
+ bootbox.dialog
+ invalid: "options"
+
+ it "throws an error", ->
+ expect(@create).to.throw /specify a message/
+
+ describe "where the argument has a button with an invalid value", ->
+ beforeEach ->
+ @create = ->
+ bootbox.dialog
+ message: "test"
+ buttons:
+ ok: "foo"
+
+ it "throws an error", ->
+ expect(@create).to.throw /button with key ok must be an object/
+
+ describe "when creating a minimal dialog", ->
+ beforeEach ->
+ @dialog = bootbox.dialog
+ message: "test"
+
+ it "adds the bootbox class to the dialog", ->
+ expect(@dialog.hasClass("bootbox")).to.be.true
+
+ it "adds the bootstrap modal class to the dialog", ->
+ expect(@dialog.hasClass("modal")).to.be.true
+
+ it "adds the fade class to the dialog", ->
+ expect(@dialog.hasClass("fade")).to.be.true
+
+ it "shows the expected message", ->
+ expect(@text(".bootbox-body")).to.equal "test"
+
+ it "does not have a header", ->
+ expect(@exists(".modal-header")).not.to.be.ok
+
+ it "has a close button inside the body", ->
+ expect(@exists(".modal-body .close")).to.be.ok
+
+ it "does not have a footer", ->
+ expect(@exists(".modal-footer")).not.to.be.ok
+
+ it "has a backdrop", ->
+ # bootstrap < 3.3.x
+ # expect(@dialog.next(".modal-backdrop").length).to.equal 1
+ # bootstrap >= 3.3.x
+ expect(@dialog.children(".modal-backdrop").length).to.equal 1
+
+ describe "when creating a dialog with a button", ->
+ beforeEach ->
+ @create = (button = {}) =>
+ @dialog = bootbox.dialog
+ message: "test"
+ buttons:
+ one: button
+
+ describe "when the button has no callback", ->
+ beforeEach ->
+ @create
+ label: "My Label"
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "shows a footer", ->
+ expect(@exists(".modal-footer")).to.be.ok
+
+ it "shows one button", ->
+ expect(@find(".btn").length).to.equal 1
+
+ it "shows the correct button text", ->
+ expect(@text(".btn")).to.equal "My Label"
+
+ it "applies the correct button class", ->
+ expect(@class(".btn", "btn-primary")).to.be.true
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when clicking the close button", ->
+ beforeEach ->
+ @dialog.find(".close").trigger "click"
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when the button has a label and callback", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @create
+ label: "Another Label"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "shows a footer", ->
+ expect(@exists(".modal-footer")).to.be.ok
+
+ it "shows the correct button text", ->
+ expect(@text(".btn")).to.equal "Another Label"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should not invoke the callback", ->
+ expect(@callback).not.to.have.been.called
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when clicking the close button", ->
+ beforeEach ->
+ @dialog.find(".close").trigger "click"
+
+ it "should not invoke the callback", ->
+ expect(@callback).not.to.have.been.called
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.called
+
+ describe "when the button has a custom class", ->
+ beforeEach ->
+ @create
+ label: "Test Label"
+ className: "btn-custom"
+
+ it "shows the correct button text", ->
+ expect(@text(".btn")).to.equal "Test Label"
+
+ 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
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ 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
+ title: "My Title"
+ message: "test"
+
+ it "has a header", ->
+ expect(@exists(".modal-header")).to.be.ok
+
+ it "shows the correct title text", ->
+ expect(@text(".modal-title")).to.equal "My Title"
+
+ it "has a close button inside the header", ->
+ expect(@exists(".modal-header .close")).to.be.ok
+
+ describe "when creating a dialog with no backdrop", ->
+ beforeEach ->
+ @dialog = bootbox.dialog
+ message: "No backdrop in sight"
+ backdrop: false
+
+ it "does not have a backdrop", ->
+ expect(@dialog.next(".modal-backdrop").length).to.equal 0
+
+ describe "when creating a dialog with no close button", ->
+ beforeEach ->
+ @dialog = bootbox.dialog
+ message: "No backdrop in sight"
+ closeButton: false
+
+ it "does not have a close button inside the body", ->
+ expect(@exists(".modal-body .close")).not.to.be.ok
+
+ describe "when creating a dialog with an onEscape handler", ->
+ beforeEach ->
+ @e = (keyCode) ->
+ $(@dialog).trigger($.Event "keyup", which: keyCode)
+
+ describe "with a simple callback", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.dialog
+ message: "Are you sure?"
+ onEscape: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+ @trigger = sinon.spy(@dialog, "trigger").withArgs "escape.close.bb"
+
+ describe "when triggering the keyup event", ->
+
+ describe "when the key is not the escape key", ->
+ beforeEach -> @e 15
+
+ it "does not trigger the escape event", ->
+ expect(@trigger).not.to.have.been.called
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when the key is the escape key", ->
+ beforeEach -> @e 27
+
+ it "triggers the escape event", ->
+ expect(@trigger).to.have.been.calledWithExactly "escape.close.bb"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "with a callback which returns false", ->
+ beforeEach ->
+ @callback = sinon.stub().returns false
+
+ @dialog = bootbox.dialog
+ message: "Are you sure?"
+ onEscape: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when triggering the escape keyup event", ->
+ beforeEach -> @e 27
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "with size option", ->
+ describe "when the size option is set to large", ->
+ beforeEach ->
+ @dialog = bootbox.dialog
+ message: "test"
+ size: "large"
+
+ it "adds the large class to the innerDialog", ->
+ expect(@dialog.children(".modal-dialog").hasClass("modal-lg")).to.be.true
+
+ describe "when the size option is set to small", ->
+ beforeEach ->
+ @dialog = bootbox.dialog
+ message: "test"
+ size: "small"
+
+ it "adds the large class to the innerDialog", ->
+ expect(@dialog.children(".modal-dialog").hasClass("modal-sm")).to.be.true
diff --git a/tests/locales.test.coffee b/tests/locales.test.coffee
new file mode 100644
index 0000000..680653e
--- /dev/null
+++ b/tests/locales.test.coffee
@@ -0,0 +1,378 @@
+describe "bootbox locales", ->
+ beforeEach ->
+
+ @setLocale = (locale) ->
+ bootbox.setLocale locale
+
+ d1 = bootbox.alert "foo"
+ d2 = bootbox.confirm "foo", -> true
+
+ @labels =
+ ok: d1.find(".btn:first").text()
+ cancel: d2.find(".btn:first").text()
+ confirm: d2.find(".btn:last").text()
+
+ describe "Invalid locale", ->
+ beforeEach ->
+ @setLocale "xx"
+
+ it "shows the default OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the default CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Cancel"
+
+ it "shows the default CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "OK"
+
+ describe "English", ->
+ beforeEach ->
+ @setLocale "en"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Cancel"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "OK"
+
+ describe "French", ->
+ beforeEach ->
+ @setLocale "fr"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Annuler"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "D'accord"
+
+ describe "German", ->
+ beforeEach ->
+ @setLocale "de"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Abbrechen"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Akzeptieren"
+
+ describe "Spanish", ->
+ beforeEach ->
+ @setLocale "es"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Cancelar"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Aceptar"
+
+ describe "Portuguese", ->
+ beforeEach ->
+ @setLocale "br"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Cancelar"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Sim"
+
+ describe "Dutch", ->
+ beforeEach ->
+ @setLocale "nl"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Annuleren"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Accepteren"
+
+ describe "Russian", ->
+ beforeEach ->
+ @setLocale "ru"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Отмена"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Применить"
+
+ describe "Indonesian", ->
+ beforeEach ->
+ @setLocale "id"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Batal"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "OK"
+
+ describe "Italian", ->
+ beforeEach ->
+ @setLocale "it"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Annulla"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Conferma"
+
+ describe "Polish", ->
+ beforeEach ->
+ @setLocale "pl"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Anuluj"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Potwierdź"
+
+ describe "Danish", ->
+ beforeEach ->
+ @setLocale "da"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Annuller"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Accepter"
+
+ describe "Chinese", ->
+ describe "Taiwan", ->
+ beforeEach ->
+ @setLocale "zh_TW"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "取消"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "確認"
+
+ describe "China", ->
+ beforeEach ->
+ @setLocale "zh_CN"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "取消"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "确认"
+
+ describe "Norwegian", ->
+ beforeEach ->
+ @setLocale "no"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Avbryt"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "OK"
+
+ describe "Swedish", ->
+ beforeEach ->
+ @setLocale "sv"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Avbryt"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "OK"
+
+ describe "Latvian", ->
+ beforeEach ->
+ @setLocale "lv"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "Labi"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Atcelt"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Apstiprināt"
+
+ describe "Lithuanian", ->
+ beforeEach ->
+ @setLocale "lt"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "Gerai"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Atšaukti"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Patvirtinti"
+
+ describe "Turkish", ->
+ beforeEach ->
+ @setLocale "tr"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "Tamam"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "İptal"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Onayla"
+
+ describe "Hebrew", ->
+ beforeEach ->
+ @setLocale "he"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "אישור"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "ביטול"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "אישור"
+
+ describe "Greek", ->
+ beforeEach ->
+ @setLocale "el"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "Εντάξει"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Ακύρωση"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Επιβεβαίωση"
+
+ describe "Japanese", ->
+ beforeEach ->
+ @setLocale "ja"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "キャンセル"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "確認"
+
+ describe "Hungarian", ->
+ beforeEach ->
+ @setLocale "hu"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Mégsem"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Megerősít"
+
+ describe "Croatian", ->
+ beforeEach ->
+ @setLocale "hr"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Odustani"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Potvrdi"
+
+ describe "Bulgarian", ->
+ beforeEach ->
+ @setLocale "bg_BG"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "Ок"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Отказ"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Потвърждавам"
+
+ describe "Thai", ->
+ beforeEach ->
+ @setLocale "th"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "ตกลง"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "ยกเลิก"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "ยืนยัน"
+
+ describe "Persian", ->
+ beforeEach ->
+ @setLocale "fa"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "قبول"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "لغو"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "تایید"
+
+ describe "Albanian", ->
+ beforeEach ->
+ @setLocale "sq"
+
+ it "shows the correct OK translation", ->
+ expect(@labels.ok).to.equal "OK"
+
+ it "shows the correct CANCEL translation", ->
+ expect(@labels.cancel).to.equal "Anulo"
+
+ it "shows the correct CONFIRM translation", ->
+ expect(@labels.confirm).to.equal "Prano"
diff --git a/tests/prompt.test.coffee b/tests/prompt.test.coffee
new file mode 100644
index 0000000..ce25d77
--- /dev/null
+++ b/tests/prompt.test.coffee
@@ -0,0 +1,1306 @@
+describe "bootbox.prompt", ->
+ beforeEach ->
+ window.bootbox = bootbox.init()
+
+ @find = (selector) -> @dialog.find selector
+ @text = (selector) -> @find(selector).text()
+ @exists = (selector) -> @find(selector).length isnt 0
+
+ describe "basic usage tests", ->
+
+ describe "with one argument", ->
+
+ describe "where the argument is not an object", ->
+ beforeEach ->
+ @create = -> bootbox.prompt "What is your name?"
+
+ it "throws an error", ->
+ expect(@create).to.throw /prompt requires a callback/
+
+ describe "where the argument is an object", ->
+ beforeEach ->
+ @options = {}
+ @create = => @dialog = bootbox.prompt @options
+
+ describe "with a title property", ->
+ beforeEach ->
+ @options.title = "What is your name?"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /prompt requires a callback/
+
+ describe "and a callback property", ->
+ describe "where the callback is not a function", ->
+ beforeEach ->
+ @options.callback = "Not a function"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /prompt requires a callback/
+
+ describe "with a callback function", ->
+ beforeEach ->
+ @options.callback = -> true
+
+ it "throws an error requiring a title", ->
+ expect(@create).to.throw /prompt requires a title/
+
+ describe "with a title and a callback", ->
+ beforeEach ->
+ @options =
+ callback: -> true
+ title: "What is your name?"
+
+ it "does not throw an error", ->
+ expect(@create).not.to.throw Error
+
+ it "creates a dialog object", ->
+ expect(@dialog).to.be.an "object"
+
+ it "applies the bootbox-prompt class to the dialog", ->
+ expect(@dialog.hasClass("bootbox-prompt")).to.be.true
+
+ it "adds the correct button labels", ->
+ expect(@dialog.find(".btn:first").text()).to.equal "Cancel"
+ expect(@dialog.find(".btn:last").text()).to.equal "OK"
+
+ it "adds the correct button classes", ->
+ expect(@dialog.find(".btn:first").hasClass("btn-default")).to.be.true
+ expect(@dialog.find(".btn:last").hasClass("btn-primary")).to.be.true
+
+ describe "with two arguments", ->
+ describe "where the second argument is not a function", ->
+ beforeEach ->
+ @create = =>
+ @dialog = bootbox.prompt "What is your name?", "callback here"
+
+ it "throws an error requiring a callback", ->
+ expect(@create).to.throw /prompt requires a callback/
+
+ describe "where the second argument is a function", ->
+ beforeEach ->
+ @create = =>
+ @dialog = bootbox.prompt "What is your name?", -> true
+
+ it "does not throw an error", ->
+ expect(@create).not.to.throw Error
+
+ it "creates a dialog object", ->
+ expect(@dialog).to.be.an "object"
+
+ it "adds the correct button labels", ->
+ expect(@text(".btn:first")).to.equal "Cancel"
+ expect(@text(".btn:last")).to.equal "OK"
+
+ it "adds the correct button classes", ->
+ expect(@dialog.find(".btn:first").hasClass("btn-default")).to.be.true
+ expect(@dialog.find(".btn:last").hasClass("btn-primary")).to.be.true
+
+ it "adds the expected dialog title", ->
+ expect(@text("h4")).to.equal "What is your name?"
+
+ it "adds a close button", ->
+ expect(@dialog.find(".modal-header .close")).to.be.ok
+
+ it "creates a form with a text input", ->
+ expect(@dialog.find("form input[type=text]")).to.be.ok
+
+ it "with no default value", ->
+ expect(@dialog.find("form input[type=text]").val()).to.equal ""
+
+ it "shows the dialog", ->
+ expect(@dialog.is(":visible")).to.be.true
+
+ describe "configuration options tests", ->
+ beforeEach ->
+ @options =
+ title: "What is your name?"
+ callback: -> true
+
+ @create = =>
+ @dialog = bootbox.prompt @options
+
+ describe "with a custom cancel button", ->
+ beforeEach ->
+ @options.buttons =
+ cancel:
+ label: "Custom cancel"
+ className: "btn-danger"
+
+ @create()
+
+ @button = @dialog.find(".btn:first")
+
+ it "adds the correct cancel button", ->
+ expect(@button.text()).to.equal "Custom cancel"
+ expect(@button.hasClass("btn-danger")).to.be.true
+
+ describe "with a custom confirm button", ->
+ beforeEach ->
+ @options.buttons =
+ confirm:
+ label: "Custom confirm"
+ className: "btn-warning"
+
+ @create()
+
+ @button = @dialog.find(".btn:last")
+
+ 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
+
+ @shown = sinon.spy()
+
+ sinon.stub bootbox, "dialog", =>
+ on: ->
+ off: ->
+ modal: @shown
+
+ @create()
+
+ it "does not show the dialog", ->
+ expect(@shown).not.to.have.been.called
+
+ describe "invalid prompt type", ->
+ beforeEach ->
+ @options.inputType = 'foobar'
+
+ it "throws an error", ->
+ expect(@create).to.throw /invalid prompt type/
+
+ describe "setting inputType text", ->
+ beforeEach ->
+ @options.inputType = "text"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows text input ", ->
+ expect(@exists("input[type='text']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='text']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='text']").hasClass("bootbox-input-text")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "John Smith"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='text']").val()).to.equal "John Smith"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter your name"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='text']").prop("placeholder")).to.equal "enter your name"
+
+ describe "with pattern", ->
+ beforeEach ->
+ @options.pattern = "\d{1,2}/\d{1,2}/\d{4}"
+ @create()
+
+ it "has correct pattern value", ->
+ expect(@find("input[type='text']").prop("pattern")).to.equal "\d{1,2}/\d{1,2}/\d{4}"
+
+ describe "with maxlength", ->
+ beforeEach ->
+ @options.maxlength = 5
+ @create()
+
+ it "has correct maxlength value", ->
+ expect(@find("input[type='text']").prop("maxlength")).to.equal 5
+
+ describe "setting inputType textarea", ->
+ beforeEach ->
+ @options.inputType = "textarea"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows text input", ->
+ expect(@exists("textarea")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("textarea").hasClass("bootbox-input")).to.be.ok
+ expect(@find("textarea").hasClass("bootbox-input-textarea")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "Once upon a time..."
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("textarea").val()).to.equal "Once upon a time..."
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter your favorite fairy tale"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("textarea").prop("placeholder")).to.equal "enter your favorite fairy tale"
+
+ describe "setting inputType email", ->
+ beforeEach ->
+ @options.inputType = "email"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows email input", ->
+ expect(@exists("input[type='email']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='email']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='email']").hasClass("bootbox-input-email")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "john at smith.com"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='email']").val()).to.equal "john at smith.com"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter your email"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='email']").prop("placeholder")).to.equal "enter your email"
+
+ describe "with pattern", ->
+ beforeEach ->
+ @options.pattern = "\d{1,2}/\d{1,2}/\d{4}"
+ @create()
+
+ it "has correct pattern value", ->
+ expect(@find("input[type='email']").prop("pattern")).to.equal "\d{1,2}/\d{1,2}/\d{4}"
+
+ describe "setting inputType password", ->
+ beforeEach ->
+ @options.inputType = "password"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows password input", ->
+ expect(@exists("input[type='password']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='password']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='password']").hasClass("bootbox-input-password")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "qwerty"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='password']").val()).to.equal "qwerty"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter your password"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='password']").prop("placeholder")).to.equal "enter your password"
+
+ describe "setting inputType select", ->
+ describe "without options", ->
+ beforeEach ->
+ @options.inputType = 'select'
+
+ it "throws an error", ->
+ expect(@create).to.throw /prompt with select requires options/
+
+ describe "with invalid options", ->
+ beforeEach ->
+ @options.inputType = 'select'
+ @options.inputOptions = 'foo'
+
+ it "throws an error", ->
+ expect(@create).to.throw "Please pass an array of input options"
+
+ describe "with empty options", ->
+ beforeEach ->
+ @options.inputType = 'select'
+ @options.inputOptions = []
+
+ it "throws an error", ->
+ expect(@create).to.throw /prompt with select requires options/
+
+ describe "with options in the wrong format", ->
+ beforeEach ->
+ @options.inputType = "select"
+ @options.inputOptions = [{foo: "bar"}]
+
+ it "throws an error", ->
+ expect(@create).to.throw /given options in wrong format/
+
+ describe "with a value but no text", ->
+ beforeEach ->
+ @options.inputType = 'select'
+ @options.inputOptions = [{value: 'bar'}]
+
+ it "throws an error", ->
+ expect(@create).to.throw /given options in wrong format/
+
+ describe "with an invalid second options", ->
+ beforeEach ->
+ @options.inputType = 'select'
+ @options.inputOptions = [
+ {value: "bar", text: "bar"}
+ {text: "foo"}
+ ]
+
+ it "throws an error", ->
+ expect(@create).to.throw /given options in wrong format/
+
+
+ describe "with valid options", ->
+ beforeEach ->
+ @options.inputType = "select"
+ @options.inputOptions = [{value: 1, text: 'foo'},{value: 2, text: 'bar'},{value: 3, text: 'foobar'}]
+
+ @create()
+
+ it "shows select input", ->
+ expect(@exists("select")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("select").hasClass("bootbox-input")).to.be.ok
+ expect(@find("select").hasClass("bootbox-input-select")).to.be.ok
+
+ it "with three options", ->
+ expect(@find("option").length).to.equal 3
+
+ describe "with zero as the first option", ->
+ beforeEach ->
+ @options.inputType = "select"
+ @options.inputOptions = [{value: 0, text: "foo"}]
+
+ @create()
+
+ it "shows the select input", ->
+ expect(@exists("select")).to.be.ok
+
+ describe "with false as the first option", ->
+ beforeEach ->
+ @options.inputType = "select"
+ @options.inputOptions = [{value: false, text: "foo"}]
+
+ @create()
+
+ it "shows the select input", ->
+ expect(@exists("select")).to.be.ok
+
+ describe "with option groups", ->
+ beforeEach ->
+ @options.inputType = 'select'
+ @options.inputOptions = [
+ {value: 1, group: 'foo', text: 'foo'}
+ {value: 2, group: 'bar', text: 'bar'}
+ {value: 3, group: 'foo', text: 'foobar'}
+ {value: 4, group: 'bar', text: 'barfoo'}
+ ]
+
+ @create()
+
+ it "shows select input", ->
+ expect(@exists("select")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("select").hasClass("bootbox-input")).to.be.ok
+ expect(@find("select").hasClass("bootbox-input-select")).to.be.ok
+
+ it "with two option group", ->
+ expect(@find("optgroup").length).to.equal 2
+
+ it "with four options", ->
+ expect(@find("option").length).to.equal 4
+
+ describe "setting inputType checkbox", ->
+ describe "without options", ->
+ beforeEach ->
+ @options.inputType = 'checkbox'
+
+ it "throws an error", ->
+ expect(@create).to.throw /prompt with checkbox requires options/
+
+ describe "with options in the wrong format", ->
+ beforeEach ->
+ @options.inputType = "checkbox"
+ @options.inputOptions = [{foo: "bar"}]
+
+ it "throws an error", ->
+ expect(@create).to.throw /given options in wrong format/
+
+ describe "with options", ->
+ beforeEach ->
+ @options.inputType = 'checkbox'
+ @options.inputOptions = [
+ {value: 1, text: 'foo'}
+ {value: 2, text: 'bar'}
+ {value: 3, text: 'foobar'}
+ ]
+
+ @create()
+
+ it "shows checkbox input", ->
+ expect(@exists("input[type='checkbox']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='checkbox']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='checkbox']").hasClass("bootbox-input-checkbox")).to.be.ok
+
+ it "with three checkboxes", ->
+ expect(@find("input[type='checkbox']").length).to.equal 3
+
+ describe "setting inputType date", ->
+ beforeEach ->
+ @options.inputType = "date"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows date input ", ->
+ expect(@exists("input[type='date']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='date']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='date']").hasClass("bootbox-input-date")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "17/08/2005"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='date']").val()).to.equal "17/08/2005"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter the date"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='date']").prop("placeholder")).to.equal "enter the date"
+
+ describe "with pattern", ->
+ beforeEach ->
+ @options.pattern = "\d{1,2}/\d{1,2}/\d{4}"
+ @create()
+
+ it "has correct pattern value", ->
+ expect(@find("input[type='date']").prop("pattern")).to.equal "\d{1,2}/\d{1,2}/\d{4}"
+
+ describe "setting inputType time", ->
+ beforeEach ->
+ @options.inputType = "time"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows time input", ->
+ expect(@exists("input[type='time']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='time']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='time']").hasClass("bootbox-input-time")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "19:02"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='time']").val()).to.equal "19:02"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter the time"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='time']").prop("placeholder")).to.equal "enter the time"
+
+ describe "with pattern", ->
+ beforeEach ->
+ @options.pattern = "\d{1,2}/\d{1,2}/\d{4}"
+ @create()
+
+ it "has correct pattern value", ->
+ expect(@find("input[type='time']").prop("pattern")).to.equal "\d{1,2}/\d{1,2}/\d{4}"
+
+ describe "setting inputType number", ->
+ beforeEach ->
+ @options.inputType = "number"
+
+ describe "without default value", ->
+ beforeEach ->
+ @create()
+
+ it "shows number input ", ->
+ expect(@exists("input[type='number']")).to.be.ok
+
+ it "has proper class", ->
+ expect(@find("input[type='number']").hasClass("bootbox-input")).to.be.ok
+ expect(@find("input[type='number']").hasClass("bootbox-input-number")).to.be.ok
+
+ describe "with default value", ->
+ beforeEach ->
+ @options.value = "300"
+ @create()
+
+ it "has correct default value", ->
+ expect(@find("input[type='number']").val()).to.equal "300"
+
+ describe "with placeholder", ->
+ beforeEach ->
+ @options.placeholder = "enter the number"
+ @create()
+
+ it "has correct placeholder value", ->
+ expect(@find("input[type='number']").prop("placeholder")).to.equal "enter the number"
+
+ describe "callback tests", ->
+ describe "with a simple callback", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your name?"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when entering no value in the text input", ->
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ""
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when submitting the form", ->
+ beforeEach ->
+ @dialog.find(".bootbox-form").trigger "submit"
+
+ it "invokes the callback with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ""
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when entering a value in the text input", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input").val "Test input"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "Test input"
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when submitting the form", ->
+ beforeEach ->
+ @dialog.find(".bootbox-form").trigger "submit"
+
+ it "invokes the callback with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "Test input"
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when dismissing the dialog by clicking the close button", ->
+ beforeEach ->
+ @dialog.find(".close").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "with a callback which returns false", ->
+ beforeEach ->
+ @callback = sinon.stub()
+ @callback.returns false
+
+ @dialog = bootbox.prompt
+ title: "What is your name?"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when entering no value in the text input", ->
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ""
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when entering a value in the text input", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input").val "Test input"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "Test input"
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when triggering the escape event", ->
+ beforeEach ->
+ @dialog.trigger "escape.close.bb"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "when dismissing the dialog by clicking the close button", ->
+ beforeEach ->
+ @dialog.find(".close").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ it "should not hide the modal", ->
+ expect(@hidden).not.to.have.been.called
+
+ describe "with a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your name?"
+ value: "Bob"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "populates the input with the default value", ->
+ expect(@dialog.find(".bootbox-input").val()).to.equal "Bob"
+
+ describe "when entering no value in the text input", ->
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "Bob"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when entering a value in the text input", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input").val "Alice"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "Alice"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "with a placeholder", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your name?"
+ placeholder: "e.g. Bob Smith"
+ callback: -> true
+
+ it "populates the input with the placeholder attribute", ->
+ expect(@dialog.find(".bootbox-input").attr("placeholder")).to.equal "e.g. Bob Smith"
+
+ describe "with inputType select", ->
+ describe "without a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your IDE?"
+ callback: @callback
+ inputType: "select"
+ inputOptions: [
+ {value: '#', text: 'Choose one'},
+ {value: 1, text: 'Vim'},
+ {value: 2, text: 'Sublime Text'},
+ {value: 3, text: 'WebStorm/PhpStorm'},
+ {value: 4, text: 'Komodo IDE'},
+ ]
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "has correct number values in list", ->
+ expect(@find(".bootbox-input-select option").length).to.equal 5
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "#"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "with a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your IDE?"
+ callback: @callback
+ value: 1
+ inputType: "select"
+ inputOptions: [
+ {value: '#', text: 'Choose one'},
+ {value: 1, text: 'Vim'},
+ {value: 2, text: 'Sublime Text'},
+ {value: 3, text: 'WebStorm/PhpStorm'},
+ {value: 4, text: 'Komodo IDE'},
+ ]
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "specified option is selected", ->
+ expect(@dialog.find(".bootbox-input-select").val()).to.equal "1"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "1"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when changing the selected option and dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input-select").val(3)
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "3"
+
+ describe "with inputType email", ->
+ describe "without a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your email?"
+ inputType: "email"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ""
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when submitting the form", ->
+ beforeEach ->
+ @dialog.find(".bootbox-form").trigger "submit"
+
+ it "invokes the callback with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ""
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when entering a value in the email input", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input-email").val "john at smith.com"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "should pass the dialog as `this`", ->
+ expect(@callback.thisValues[0]).to.equal @dialog
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "john at smith.com"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "with a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your email?"
+ inputType: "email"
+ value: "john at smith.com"
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "john at smith.com"
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when submitting the form", ->
+ beforeEach ->
+ @dialog.find(".bootbox-form").trigger "submit"
+
+ it "invokes the callback with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "john at smith.com"
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when changing a value in the email input", ->
+ beforeEach ->
+ @dialog.find(".bootbox-input-email").val "smith at john.com"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly "smith at john.com"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "with input type checkbox", ->
+ describe "without a default value", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your IDE?"
+ inputType: 'checkbox'
+ inputOptions: [
+ {value: 1, text: 'Vim'},
+ {value: 2, text: 'Sublime Text'},
+ {value: 3, text: 'WebStorm/PhpStorm'},
+ {value: 4, text: 'Komodo IDE'},
+ ]
+ callback: @callback
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with an undefined value", ->
+ expect(@callback).to.have.been.calledWithExactly []
+
+ it "should hide the modal", ->
+ expect(@hidden).to.have.been.calledWithExactly "hide"
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "with default value", ->
+ describe "one value checked", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your IDE?"
+ callback: @callback
+ value: 2
+ inputType: "checkbox"
+ inputOptions: [
+ {value: 1, text: 'Vim'},
+ {value: 2, text: 'Sublime Text'},
+ {value: 3, text: 'WebStorm/PhpStorm'},
+ {value: 4, text: 'Komodo IDE'},
+ ]
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "specified checkbox is checked", ->
+ expect(@dialog.find("input:checkbox:checked").val()).to.equal "2"
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ["2"]
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when changing the checked option and dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find("input:checkbox:checked").prop('checked', false)
+ @dialog.find("input:checkbox[value=3]").prop('checked', true)
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when changing the selected option and dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find("input:checkbox:checked").prop('checked', false)
+ @dialog.find("input:checkbox[value=3]").prop('checked', true)
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ["3"]
+
+ describe "multiple value checked", ->
+ beforeEach ->
+ @callback = sinon.spy()
+
+ @dialog = bootbox.prompt
+ title: "What is your IDE?"
+ callback: @callback
+ value: [2, 3]
+ inputType: "checkbox"
+ inputOptions: [
+ {value: 1, text: 'Vim'}
+ {value: 2, text: 'Sublime Text'}
+ {value: 3, text: 'WebStorm/PhpStorm'}
+ {value: 4, text: 'Komodo IDE'}
+ ]
+
+ @hidden = sinon.spy @dialog, "modal"
+
+ it "specified checkboxes are checked", ->
+ checked = []
+
+ @dialog.find("input:checkbox:checked").each (foo, bar) =>
+ checked.push $(bar).val()
+
+ expect(checked).to.deep.equal ["2", "3"]
+
+ describe "when dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ["2", "3"]
+
+ describe "when dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when changing the checked options and dismissing the dialog by clicking Cancel", ->
+ beforeEach ->
+ @dialog.find("input:checkbox:checked").prop('checked', false)
+ @dialog.find("input:checkbox[value=1]").prop('checked', true)
+ @dialog.find("input:checkbox[value=4]").prop('checked', true)
+ @dialog.find(".btn-default").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly null
+
+ describe "when changing the checked options and dismissing the dialog by clicking OK", ->
+ beforeEach ->
+ @dialog.find("input:checkbox:checked").prop('checked', false)
+ @dialog.find("input:checkbox[value=1]").prop('checked', true)
+ @dialog.find("input:checkbox[value=4]").prop('checked', true)
+ @dialog.find(".btn-primary").trigger "click"
+
+ it "should invoke the callback", ->
+ expect(@callback).to.have.been.called
+
+ it "with the correct value", ->
+ expect(@callback).to.have.been.calledWithExactly ["1", "4"]
+
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/libjs-bootbox.git
More information about the Pkg-javascript-commits
mailing list