├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── README.md
├── bower.json
├── changelog.txt
├── composer.json
├── dist
├── css
│ ├── bootstrap-dialog.css
│ └── bootstrap-dialog.min.css
├── js
│ ├── bootstrap-dialog.js
│ └── bootstrap-dialog.min.js
└── less
│ └── bootstrap-dialog.less
├── examples
├── images
│ └── pig.ico
├── index.html
├── play
│ ├── append-to-div.html
│ ├── button-event.html
│ ├── custom-dialog-id.html
│ ├── only-one-dialog.html
│ ├── reopen-dialog.html
│ ├── spinning-icon.html
│ └── tabindex.html
└── remote.html
├── gulpfile.js
├── package.json
└── src
├── css
└── bootstrap-dialog.css
├── js
└── bootstrap-dialog.js
└── less
└── bootstrap-dialog.less
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "node": true
4 | },
5 |
6 | "rules": {
7 | "brace-style": [2, "1tbs"],
8 | "default-case": 2,
9 | "func-style": [2, "declaration"],
10 | "guard-for-in": 2,
11 | "no-floating-decimal": 2,
12 | "no-nested-ternary": 2,
13 | "radix": 2,
14 | "space-unary-word-ops": 2,
15 | "space-after-keywords": [2, "always"],
16 | "valid-jsdoc": [2, {
17 | "prefer": {
18 | "return": "returns"
19 | }
20 | }],
21 | "quotes": [1, "single", "allow-avoiding-escaped-quotes"],
22 | "wrap-iife": 2
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | nbproject
2 | node_modules
3 | bower_components
4 | /vendor/
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nakupanda/bootstrap3-dialog/a491a98c97921114883ad44e5715fe28396dbaea/.npmignore
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | bootstrap-dialog
2 | ================
3 |
4 | [](https://github.com/nakupanda/bootstrap3-dialog/releases/latest)
5 |
6 | Make use of Bootstrap Modal more monkey-friendly.
7 |
8 | See live examples here: http://nakupanda.github.io/bootstrap3-dialog/
9 |
10 | Please note that this project is for Bootstrap 3 .
11 |
12 | Thanks for [akinoniku](https://github.com/akinoniku)'s suggestions on dialog appearance.
13 |
14 | ================
15 |
16 | ## Ask a question
17 |
18 | It's recommended to provide online examples when asking questions or reporting bugs.
19 | Fork this all-ready jsfiddle and start writing your example:
20 | http://jsfiddle.net/o5k0eaws/1/
21 |
22 | ================
23 |
24 | ## Use Guidances from contributors
25 |
26 | How to use bootstrap-dialog as Rails 4 confirm - @[Genkilabs](https://github.com/Genkilabs)
27 |
28 | How to use in ReactJS - @[sonhan](https://github.com/sonhan)
29 |
30 | ================
31 | ## Reference to CDN
32 |
33 | ```
34 | https://cdnjs.cloudflare.com/ajax/libs/bootstrap3-dialog/1.34.7/css/bootstrap-dialog.min.css
35 | https://cdnjs.cloudflare.com/ajax/libs/bootstrap3-dialog/1.34.7/js/bootstrap-dialog.min.js
36 | ```
37 | ================
38 |
39 | ## Install using Bower
40 |
41 | ```
42 | bower install bootstrap-dialog
43 | ```
44 |
45 | Or
46 |
47 | ```
48 | bower install bootstrap3-dialog
49 | ```
50 |
51 | ================
52 |
53 | ## Install using npm
54 |
55 | ```
56 | npm install --save bootstrap3-dialog
57 | ```
58 |
59 | ================
60 |
61 | ## Build instructions:
62 |
63 | Prepare:
64 |
65 | ```
66 | npm install
67 | ```
68 |
69 | Build:
70 |
71 | ```
72 | gulp dist
73 | ```
74 |
75 | ================
76 |
77 | Licensed under The MIT License.
78 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootstrap3-dialog",
3 | "description": "Make use of Bootstrap Modal more monkey-friendly. http://nakupanda.github.io/bootstrap3-dialog/",
4 | "version": "1.35.4",
5 | "keywords": [
6 | "css",
7 | "js",
8 | "less",
9 | "mobile-first",
10 | "responsive",
11 | "front-end",
12 | "framework",
13 | "web"
14 | ],
15 | "homepage": "http://nakupanda.github.io/bootstrap3-dialog/",
16 | "main": [
17 | "dist/less/bootstrap-dialog.less",
18 | "dist/css/bootstrap-dialog.min.css",
19 | "dist/js/bootstrap-dialog.min.js"
20 | ],
21 | "license": "MIT",
22 | "ignore": [
23 | "source",
24 | "spec",
25 | ".bowerrc",
26 | ".gitignore",
27 | ".jshintignore",
28 | ".jshintrc",
29 | "bower.json",
30 | "gruntfile.js",
31 | "package.json",
32 | "README.md"
33 | ],
34 | "dependencies": {
35 | "bootstrap": ">= 3.1.0",
36 | "jquery": ">= 1.9.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/changelog.txt:
--------------------------------------------------------------------------------
1 | LASTEST NOT RELEASED
2 | ------------------------------
3 | * Merged #347 *
4 |
5 | V1.35.4
6 | ------------------------------
7 | * Refs #300 *
8 | * Refs #308 *
9 | * Refs #232 *
10 | * Refs #334 *
11 | * Refs #331 *
12 |
13 | V1.35.3
14 | ------------------------------
15 | * Refs #144 *
16 | * Refs #284 *
17 | * Refs #231 *
18 | * Refs #271 *
19 | * Refs #294 *
20 |
21 | V1.35.2
22 | ------------------------------
23 | * Refs #251 Close icon on the top right is configurable *
24 | * Refs #249 *
25 | * Refs #256 *
26 |
27 | V1.35.1
28 | ------------------------------
29 | * Refs #243 *
30 |
31 | V1.35.0
32 | ------------------------------
33 | * Refs #224 *
34 | * Refs #208 *
35 | * Refs #233 *
36 | * Refs #247 *
37 | * Refs #248 *
38 |
39 | V1.34.9
40 | ------------------------------
41 | * Fixed #221 *
42 |
43 | V1.34.8
44 | ------------------------------
45 | * Set 'realized' status to false when closing a 'autodestroy' dialog. *
46 | * Merged #136 *
47 | * Refs #210 *
48 | * Merged #219 *
49 |
50 | V1.34.7
51 | ------------------------------
52 | * Refs #176 *
53 | * Refs #109, Add methods getDialog(), setDialog() and addDialog() to BootstrapDialog. *
54 | * Refs #201 *
55 | * Refs #200 *
56 |
57 | V1.34.6
58 | ------------------------------
59 | * Refs #159 *
60 | * Refs #160*
61 | * Refs #179, removed local assets for example page, and used files hosted on CDN instead. *
62 |
63 | V1.34.5
64 | ------------------------------
65 | * Merged #137, Add missing less and remove stray css file in src folder *
66 | * Tabindex is a customizable option now. *
67 | * Refs #142 *
68 | * Refs #145 *
69 |
70 | V1.34.4
71 | ------------------------------
72 | * Updated required Bootstrap version. *
73 |
74 | V1.34.3
75 | ------------------------------
76 | * Fixed #125, a bug that dialog footer won't be shown if it was hidden by a no button realization. *
77 | * Refs #126. Adding a data 'button' to the created button. Passing original event object to button callback action(dialog, event). *
78 | * Support Bootstrap v3.3.4
79 |
80 | V1.34.2
81 | ------------------------------
82 | * FIXED #102 *
83 | * FIXED #121 *
84 | * Implemented modal-sm, REFS #105 *
85 | * More controls on confirm dialog, REFS #105 *
86 | * Added I18N example *
87 |
88 | V1.34.1
89 | ------------------------------
90 | * Added more compatible methods to make BootstrapDialog works better with older version of Bootstrap Modal. *
91 |
92 | V1.34.0
93 | ------------------------------
94 | * FIXED #84 *
95 | * Support Bootstrap Modal v3.3.0 *
96 |
97 | V1.33.5
98 | ------------------------------
99 | * PULL REQUEST: #72 *
100 | * PULL REQUEST: #83 *
101 | * Fixed a bug that after dragging the dialog to another place, the original place prevents closing the dialog by clicking on backdrop. *
102 |
103 | V1.33.4
104 | ------------------------------
105 | * RE-FIXED #56 *
106 |
107 | V1.33.3
108 | ------------------------------
109 | * FIXED #62 *
110 | * IMPLEMENTED #67 *
111 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cross-solution/bootstrap3-dialog",
3 | "description": "Make use of Bootstrap Modal more monkey-friendly.",
4 | "license": "MIT",
5 | "authors": [
6 | {
7 | "name": "Nakupanda",
8 | "email": "javanoob@hotmail.com"
9 | }
10 | ],
11 | "require": {
12 | "components/jquery": "*",
13 | "twbs/bootstrap": "3.*"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/dist/css/bootstrap-dialog.css:
--------------------------------------------------------------------------------
1 | .bootstrap-dialog {
2 | /* dialog types */
3 | /**
4 | * Icon animation
5 | * Copied from font-awesome: http://fontawesome.io/
6 | **/
7 | /** End of icon animation **/
8 | }
9 | .bootstrap-dialog .modal-header {
10 | border-top-left-radius: 4px;
11 | border-top-right-radius: 4px;
12 | }
13 | .bootstrap-dialog .bootstrap-dialog-title {
14 | color: #fff;
15 | display: inline-block;
16 | font-size: 16px;
17 | }
18 | .bootstrap-dialog .bootstrap-dialog-message {
19 | font-size: 14px;
20 | }
21 | .bootstrap-dialog .bootstrap-dialog-button-icon {
22 | margin-right: 3px;
23 | }
24 | .bootstrap-dialog .bootstrap-dialog-close-button {
25 | font-size: 20px;
26 | float: right;
27 | opacity: 0.9;
28 | filter: alpha(opacity=90);
29 | }
30 | .bootstrap-dialog .bootstrap-dialog-close-button:hover {
31 | cursor: pointer;
32 | opacity: 1;
33 | filter: alpha(opacity=100);
34 | }
35 | .bootstrap-dialog.type-default .modal-header {
36 | background-color: #ffffff;
37 | }
38 | .bootstrap-dialog.type-default .bootstrap-dialog-title {
39 | color: #333;
40 | }
41 | .bootstrap-dialog.type-info .modal-header {
42 | background-color: #5bc0de;
43 | }
44 | .bootstrap-dialog.type-primary .modal-header {
45 | background-color: #337ab7;
46 | }
47 | .bootstrap-dialog.type-success .modal-header {
48 | background-color: #5cb85c;
49 | }
50 | .bootstrap-dialog.type-warning .modal-header {
51 | background-color: #f0ad4e;
52 | }
53 | .bootstrap-dialog.type-danger .modal-header {
54 | background-color: #d9534f;
55 | }
56 | .bootstrap-dialog.size-large .bootstrap-dialog-title {
57 | font-size: 24px;
58 | }
59 | .bootstrap-dialog.size-large .bootstrap-dialog-close-button {
60 | font-size: 30px;
61 | }
62 | .bootstrap-dialog.size-large .bootstrap-dialog-message {
63 | font-size: 18px;
64 | }
65 | .bootstrap-dialog .icon-spin {
66 | display: inline-block;
67 | -moz-animation: spin 2s infinite linear;
68 | -o-animation: spin 2s infinite linear;
69 | -webkit-animation: spin 2s infinite linear;
70 | animation: spin 2s infinite linear;
71 | }
72 | @-moz-keyframes spin {
73 | 0% {
74 | -moz-transform: rotate(0deg);
75 | }
76 | 100% {
77 | -moz-transform: rotate(359deg);
78 | }
79 | }
80 | @-webkit-keyframes spin {
81 | 0% {
82 | -webkit-transform: rotate(0deg);
83 | }
84 | 100% {
85 | -webkit-transform: rotate(359deg);
86 | }
87 | }
88 | @-o-keyframes spin {
89 | 0% {
90 | -o-transform: rotate(0deg);
91 | }
92 | 100% {
93 | -o-transform: rotate(359deg);
94 | }
95 | }
96 | @-ms-keyframes spin {
97 | 0% {
98 | -ms-transform: rotate(0deg);
99 | }
100 | 100% {
101 | -ms-transform: rotate(359deg);
102 | }
103 | }
104 | @keyframes spin {
105 | 0% {
106 | transform: rotate(0deg);
107 | }
108 | 100% {
109 | transform: rotate(359deg);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/dist/css/bootstrap-dialog.min.css:
--------------------------------------------------------------------------------
1 | .bootstrap-dialog .modal-header{border-top-left-radius:4px;border-top-right-radius:4px}.bootstrap-dialog .bootstrap-dialog-title{color:#fff;display:inline-block;font-size:16px}.bootstrap-dialog .bootstrap-dialog-message{font-size:14px}.bootstrap-dialog .bootstrap-dialog-button-icon{margin-right:3px}.bootstrap-dialog .bootstrap-dialog-close-button{font-size:20px;float:right;opacity:.9;filter:alpha(opacity=90)}.bootstrap-dialog .bootstrap-dialog-close-button:hover{cursor:pointer;opacity:1;filter:alpha(opacity=100)}.bootstrap-dialog.type-default .modal-header{background-color:#fff}.bootstrap-dialog.type-default .bootstrap-dialog-title{color:#333}.bootstrap-dialog.type-info .modal-header{background-color:#5bc0de}.bootstrap-dialog.type-primary .modal-header{background-color:#337ab7}.bootstrap-dialog.type-success .modal-header{background-color:#5cb85c}.bootstrap-dialog.type-warning .modal-header{background-color:#f0ad4e}.bootstrap-dialog.type-danger .modal-header{background-color:#d9534f}.bootstrap-dialog.size-large .bootstrap-dialog-title{font-size:24px}.bootstrap-dialog.size-large .bootstrap-dialog-close-button{font-size:30px}.bootstrap-dialog.size-large .bootstrap-dialog-message{font-size:18px}.bootstrap-dialog .icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
--------------------------------------------------------------------------------
/dist/js/bootstrap-dialog.js:
--------------------------------------------------------------------------------
1 | /* global define */
2 |
3 | /* ================================================
4 | * Make use of Bootstrap's modal more monkey-friendly.
5 | *
6 | * For Bootstrap 3.
7 | *
8 | * javanoob@hotmail.com
9 | *
10 | * https://github.com/nakupanda/bootstrap3-dialog
11 | *
12 | * Licensed under The MIT License.
13 | * ================================================ */
14 | (function (root, factory) {
15 |
16 | "use strict";
17 |
18 | // CommonJS module is defined
19 | if (typeof module !== 'undefined' && module.exports) {
20 | module.exports = factory(require('jquery'), require('bootstrap'));
21 | }
22 | // AMD module is defined
23 | else if (typeof define === "function" && define.amd) {
24 | define("bootstrap-dialog", ["jquery", "bootstrap"], function ($) {
25 | return factory($);
26 | });
27 | } else {
28 | // planted over the root!
29 | root.BootstrapDialog = factory(root.jQuery);
30 | }
31 |
32 | }(this, function ($) {
33 |
34 | "use strict";
35 |
36 | /* ================================================
37 | * Definition of BootstrapDialogModal.
38 | * Extend Bootstrap Modal and override some functions.
39 | * BootstrapDialogModal === Modified Modal.
40 | * ================================================ */
41 | var Modal = $.fn.modal.Constructor;
42 | var BootstrapDialogModal = function (element, options) {
43 | Modal.call(this, element, options);
44 | };
45 | BootstrapDialogModal.getModalVersion = function () {
46 | var version = null;
47 | if (typeof $.fn.modal.Constructor.VERSION === 'undefined') {
48 | version = 'v3.1';
49 | } else if (/3\.2\.\d+/.test($.fn.modal.Constructor.VERSION)) {
50 | version = 'v3.2';
51 | } else if (/3\.3\.[1,2]/.test($.fn.modal.Constructor.VERSION)) {
52 | version = 'v3.3'; // v3.3.1, v3.3.2
53 | } else {
54 | version = 'v3.3.4';
55 | }
56 |
57 | return version;
58 | };
59 | BootstrapDialogModal.ORIGINAL_BODY_PADDING = parseInt(($('body').css('padding-right') || 0), 10);
60 | BootstrapDialogModal.METHODS_TO_OVERRIDE = {};
61 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.1'] = {};
62 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.2'] = {
63 | hide: function (e) {
64 | if (e) {
65 | e.preventDefault();
66 | }
67 | e = $.Event('hide.bs.modal');
68 |
69 | this.$element.trigger(e);
70 |
71 | if (!this.isShown || e.isDefaultPrevented()) {
72 | return;
73 | }
74 |
75 | this.isShown = false;
76 |
77 | // Remove css class 'modal-open' when the last opened dialog is closing.
78 | var openedDialogs = this.getGlobalOpenedDialogs();
79 | if (openedDialogs.length === 0) {
80 | this.$body.removeClass('modal-open');
81 | }
82 |
83 | this.resetScrollbar();
84 | this.escape();
85 |
86 | $(document).off('focusin.bs.modal');
87 |
88 | this.$element
89 | .removeClass('in')
90 | .attr('aria-hidden', true)
91 | .off('click.dismiss.bs.modal');
92 |
93 | $.support.transition && this.$element.hasClass('fade') ?
94 | this.$element
95 | .one('bsTransitionEnd', $.proxy(this.hideModal, this))
96 | .emulateTransitionEnd(300) :
97 | this.hideModal();
98 | }
99 | };
100 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3'] = {
101 | /**
102 | * Overrided.
103 | *
104 | * @returns {undefined}
105 | */
106 | setScrollbar: function () {
107 | var bodyPad = BootstrapDialogModal.ORIGINAL_BODY_PADDING;
108 | if (this.bodyIsOverflowing) {
109 | this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
110 | }
111 | },
112 | /**
113 | * Overrided.
114 | *
115 | * @returns {undefined}
116 | */
117 | resetScrollbar: function () {
118 | var openedDialogs = this.getGlobalOpenedDialogs();
119 | if (openedDialogs.length === 0) {
120 | this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
121 | }
122 | },
123 | /**
124 | * Overrided.
125 | *
126 | * @returns {undefined}
127 | */
128 | hideModal: function () {
129 | this.$element.hide();
130 | this.backdrop($.proxy(function () {
131 | var openedDialogs = this.getGlobalOpenedDialogs();
132 | if (openedDialogs.length === 0) {
133 | this.$body.removeClass('modal-open');
134 | }
135 | this.resetAdjustments();
136 | this.resetScrollbar();
137 | this.$element.trigger('hidden.bs.modal');
138 | }, this));
139 | }
140 | };
141 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3.4'] = $.extend({}, BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3']);
142 | BootstrapDialogModal.prototype = {
143 | constructor: BootstrapDialogModal,
144 | /**
145 | * New function, to get the dialogs that opened by BootstrapDialog.
146 | *
147 | * @returns {undefined}
148 | */
149 | getGlobalOpenedDialogs: function () {
150 | var openedDialogs = [];
151 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
152 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
153 | openedDialogs.push(dialogInstance);
154 | }
155 | });
156 |
157 | return openedDialogs;
158 | }
159 | };
160 |
161 | // Add compatible methods.
162 | BootstrapDialogModal.prototype = $.extend(BootstrapDialogModal.prototype, Modal.prototype, BootstrapDialogModal.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
163 |
164 | /* ================================================
165 | * Definition of BootstrapDialog.
166 | * ================================================ */
167 | var BootstrapDialog = function (options) {
168 | this.defaultOptions = $.extend(true, {
169 | id: BootstrapDialog.newGuid(),
170 | buttons: [],
171 | data: {},
172 | onshow: null,
173 | onshown: null,
174 | onhide: null,
175 | onhidden: null
176 | }, BootstrapDialog.defaultOptions);
177 | this.indexedButtons = {};
178 | this.registeredButtonHotkeys = {};
179 | this.draggableData = {
180 | isMouseDown: false,
181 | mouseOffset: {}
182 | };
183 | this.realized = false;
184 | this.opened = false;
185 | this.initOptions(options);
186 | this.holdThisInstance();
187 | };
188 |
189 | BootstrapDialog.BootstrapDialogModal = BootstrapDialogModal;
190 |
191 | /**
192 | * Some constants.
193 | */
194 | BootstrapDialog.NAMESPACE = 'bootstrap-dialog';
195 | BootstrapDialog.TYPE_DEFAULT = 'type-default';
196 | BootstrapDialog.TYPE_INFO = 'type-info';
197 | BootstrapDialog.TYPE_PRIMARY = 'type-primary';
198 | BootstrapDialog.TYPE_SUCCESS = 'type-success';
199 | BootstrapDialog.TYPE_WARNING = 'type-warning';
200 | BootstrapDialog.TYPE_DANGER = 'type-danger';
201 | BootstrapDialog.DEFAULT_TEXTS = {};
202 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_DEFAULT] = 'Information';
203 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_INFO] = 'Information';
204 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_PRIMARY] = 'Information';
205 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_SUCCESS] = 'Success';
206 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_WARNING] = 'Warning';
207 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_DANGER] = 'Danger';
208 | BootstrapDialog.DEFAULT_TEXTS['OK'] = 'OK';
209 | BootstrapDialog.DEFAULT_TEXTS['CANCEL'] = 'Cancel';
210 | BootstrapDialog.DEFAULT_TEXTS['CONFIRM'] = 'Confirmation';
211 | BootstrapDialog.SIZE_NORMAL = 'size-normal';
212 | BootstrapDialog.SIZE_SMALL = 'size-small';
213 | BootstrapDialog.SIZE_WIDE = 'size-wide'; // size-wide is equal to modal-lg
214 | BootstrapDialog.SIZE_LARGE = 'size-large';
215 | BootstrapDialog.BUTTON_SIZES = {};
216 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_NORMAL] = '';
217 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_SMALL] = '';
218 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_WIDE] = '';
219 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_LARGE] = 'btn-lg';
220 | BootstrapDialog.ICON_SPINNER = 'glyphicon glyphicon-asterisk';
221 | BootstrapDialog.BUTTONS_ORDER_CANCEL_OK = 'btns-order-cancel-ok';
222 | BootstrapDialog.BUTTONS_ORDER_OK_CANCEL = 'btns-order-ok-cancel';
223 |
224 | /**
225 | * Default options.
226 | */
227 | BootstrapDialog.defaultOptions = {
228 | type: BootstrapDialog.TYPE_PRIMARY,
229 | size: BootstrapDialog.SIZE_NORMAL,
230 | cssClass: '',
231 | title: null,
232 | message: null,
233 | nl2br: true,
234 | closable: true,
235 | closeByBackdrop: true,
236 | closeByKeyboard: true,
237 | closeIcon: '×',
238 | spinicon: BootstrapDialog.ICON_SPINNER,
239 | autodestroy: true,
240 | draggable: false,
241 | animate: true,
242 | description: '',
243 | tabindex: -1,
244 | btnsOrder: BootstrapDialog.BUTTONS_ORDER_CANCEL_OK
245 | };
246 |
247 | /**
248 | * Config default options.
249 | */
250 | BootstrapDialog.configDefaultOptions = function (options) {
251 | BootstrapDialog.defaultOptions = $.extend(true, BootstrapDialog.defaultOptions, options);
252 | };
253 |
254 | /**
255 | * Open / Close all created dialogs all at once.
256 | */
257 | BootstrapDialog.dialogs = {};
258 | BootstrapDialog.openAll = function () {
259 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
260 | dialogInstance.open();
261 | });
262 | };
263 | BootstrapDialog.closeAll = function () {
264 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
265 | dialogInstance.close();
266 | });
267 | };
268 |
269 | /**
270 | * Get dialog instance by given id.
271 | *
272 | * @returns dialog instance
273 | */
274 | BootstrapDialog.getDialog = function (id) {
275 | var dialog = null;
276 | if (typeof BootstrapDialog.dialogs[id] !== 'undefined') {
277 | dialog = BootstrapDialog.dialogs[id];
278 | }
279 |
280 | return dialog;
281 | };
282 |
283 | /**
284 | * Set a dialog.
285 | *
286 | * @returns the dialog that has just been set.
287 | */
288 | BootstrapDialog.setDialog = function (dialog) {
289 | BootstrapDialog.dialogs[dialog.getId()] = dialog;
290 |
291 | return dialog;
292 | };
293 |
294 | /**
295 | * Alias of BootstrapDialog.setDialog(dialog)
296 | *
297 | * @param {type} dialog
298 | * @returns {unresolved}
299 | */
300 | BootstrapDialog.addDialog = function (dialog) {
301 | return BootstrapDialog.setDialog(dialog);
302 | };
303 |
304 | /**
305 | * Move focus to next visible dialog.
306 | */
307 | BootstrapDialog.moveFocus = function () {
308 | var lastDialogInstance = null;
309 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
310 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
311 | lastDialogInstance = dialogInstance;
312 | }
313 | });
314 | if (lastDialogInstance !== null) {
315 | lastDialogInstance.getModal().focus();
316 | }
317 | };
318 |
319 | BootstrapDialog.METHODS_TO_OVERRIDE = {};
320 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.1'] = {
321 | handleModalBackdropEvent: function () {
322 | this.getModal().on('click', {dialog: this}, function (event) {
323 | event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
324 | });
325 |
326 | return this;
327 | },
328 | /**
329 | * To make multiple opened dialogs look better.
330 | *
331 | * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
332 | */
333 | updateZIndex: function () {
334 | if (this.isOpened()) {
335 | var zIndexBackdrop = 1040;
336 | var zIndexModal = 1050;
337 | var dialogCount = 0;
338 | $.each(BootstrapDialog.dialogs, function (dialogId, dialogInstance) {
339 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
340 | dialogCount++;
341 | }
342 | });
343 | var $modal = this.getModal();
344 | var $backdrop = $modal.data('bs.modal').$backdrop;
345 | $modal.css('z-index', zIndexModal + (dialogCount - 1) * 20);
346 | $backdrop.css('z-index', zIndexBackdrop + (dialogCount - 1) * 20);
347 | }
348 |
349 | return this;
350 | },
351 | open: function () {
352 | !this.isRealized() && this.realize();
353 | this.getModal().modal('show');
354 | this.updateZIndex();
355 |
356 | return this;
357 | }
358 | };
359 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.2'] = {
360 | handleModalBackdropEvent: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['handleModalBackdropEvent'],
361 | updateZIndex: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['updateZIndex'],
362 | open: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['open']
363 | };
364 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.3'] = {};
365 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.3.4'] = $.extend({}, BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']);
366 | BootstrapDialog.prototype = {
367 | constructor: BootstrapDialog,
368 | initOptions: function (options) {
369 | this.options = $.extend(true, this.defaultOptions, options);
370 |
371 | return this;
372 | },
373 | holdThisInstance: function () {
374 | BootstrapDialog.addDialog(this);
375 |
376 | return this;
377 | },
378 | initModalStuff: function () {
379 | this.setModal(this.createModal())
380 | .setModalDialog(this.createModalDialog())
381 | .setModalContent(this.createModalContent())
382 | .setModalHeader(this.createModalHeader())
383 | .setModalBody(this.createModalBody())
384 | .setModalFooter(this.createModalFooter());
385 |
386 | this.getModal().append(this.getModalDialog());
387 | this.getModalDialog().append(this.getModalContent());
388 | this.getModalContent()
389 | .append(this.getModalHeader())
390 | .append(this.getModalBody())
391 | .append(this.getModalFooter());
392 |
393 | return this;
394 | },
395 | createModal: function () {
396 | var $modal = $('
');
397 | $modal.prop('id', this.getId());
398 | $modal.attr('aria-labelledby', this.getId() + '_title');
399 |
400 | return $modal;
401 | },
402 | getModal: function () {
403 | return this.$modal;
404 | },
405 | setModal: function ($modal) {
406 | this.$modal = $modal;
407 |
408 | return this;
409 | },
410 | createModalDialog: function () {
411 | return $('
');
412 | },
413 | getModalDialog: function () {
414 | return this.$modalDialog;
415 | },
416 | setModalDialog: function ($modalDialog) {
417 | this.$modalDialog = $modalDialog;
418 |
419 | return this;
420 | },
421 | createModalContent: function () {
422 | return $('
');
423 | },
424 | getModalContent: function () {
425 | return this.$modalContent;
426 | },
427 | setModalContent: function ($modalContent) {
428 | this.$modalContent = $modalContent;
429 |
430 | return this;
431 | },
432 | createModalHeader: function () {
433 | return $('');
434 | },
435 | getModalHeader: function () {
436 | return this.$modalHeader;
437 | },
438 | setModalHeader: function ($modalHeader) {
439 | this.$modalHeader = $modalHeader;
440 |
441 | return this;
442 | },
443 | createModalBody: function () {
444 | return $('
');
445 | },
446 | getModalBody: function () {
447 | return this.$modalBody;
448 | },
449 | setModalBody: function ($modalBody) {
450 | this.$modalBody = $modalBody;
451 |
452 | return this;
453 | },
454 | createModalFooter: function () {
455 | return $('');
456 | },
457 | getModalFooter: function () {
458 | return this.$modalFooter;
459 | },
460 | setModalFooter: function ($modalFooter) {
461 | this.$modalFooter = $modalFooter;
462 |
463 | return this;
464 | },
465 | createDynamicContent: function (rawContent) {
466 | var content = null;
467 | if (typeof rawContent === 'function') {
468 | content = rawContent.call(rawContent, this);
469 | } else {
470 | content = rawContent;
471 | }
472 | if (typeof content === 'string') {
473 | content = this.formatStringContent(content);
474 | }
475 |
476 | return content;
477 | },
478 | formatStringContent: function (content) {
479 | if (this.options.nl2br) {
480 | return content.replace(/\r\n/g, ' ').replace(/[\r\n]/g, ' ');
481 | }
482 |
483 | return content;
484 | },
485 | setData: function (key, value) {
486 | this.options.data[key] = value;
487 |
488 | return this;
489 | },
490 | getData: function (key) {
491 | return this.options.data[key];
492 | },
493 | setId: function (id) {
494 | this.options.id = id;
495 |
496 | return this;
497 | },
498 | getId: function () {
499 | return this.options.id;
500 | },
501 | getType: function () {
502 | return this.options.type;
503 | },
504 | setType: function (type) {
505 | this.options.type = type;
506 | this.updateType();
507 |
508 | return this;
509 | },
510 | updateType: function () {
511 | if (this.isRealized()) {
512 | var types = [BootstrapDialog.TYPE_DEFAULT,
513 | BootstrapDialog.TYPE_INFO,
514 | BootstrapDialog.TYPE_PRIMARY,
515 | BootstrapDialog.TYPE_SUCCESS,
516 | BootstrapDialog.TYPE_WARNING,
517 | BootstrapDialog.TYPE_DANGER];
518 |
519 | this.getModal().removeClass(types.join(' ')).addClass(this.getType());
520 | }
521 |
522 | return this;
523 | },
524 | getSize: function () {
525 | return this.options.size;
526 | },
527 | setSize: function (size) {
528 | this.options.size = size;
529 | this.updateSize();
530 |
531 | return this;
532 | },
533 | updateSize: function () {
534 | if (this.isRealized()) {
535 | var dialog = this;
536 |
537 | // Dialog size
538 | this.getModal().removeClass(BootstrapDialog.SIZE_NORMAL)
539 | .removeClass(BootstrapDialog.SIZE_SMALL)
540 | .removeClass(BootstrapDialog.SIZE_WIDE)
541 | .removeClass(BootstrapDialog.SIZE_LARGE);
542 | this.getModal().addClass(this.getSize());
543 |
544 | // Smaller dialog.
545 | this.getModalDialog().removeClass('modal-sm');
546 | if (this.getSize() === BootstrapDialog.SIZE_SMALL) {
547 | this.getModalDialog().addClass('modal-sm');
548 | }
549 |
550 | // Wider dialog.
551 | this.getModalDialog().removeClass('modal-lg');
552 | if (this.getSize() === BootstrapDialog.SIZE_WIDE) {
553 | this.getModalDialog().addClass('modal-lg');
554 | }
555 |
556 | // Button size
557 | $.each(this.options.buttons, function (index, button) {
558 | var $button = dialog.getButton(button.id);
559 | var buttonSizes = ['btn-lg', 'btn-sm', 'btn-xs'];
560 | var sizeClassSpecified = false;
561 | if (typeof button['cssClass'] === 'string') {
562 | var btnClasses = button['cssClass'].split(' ');
563 | $.each(btnClasses, function (index, btnClass) {
564 | if ($.inArray(btnClass, buttonSizes) !== -1) {
565 | sizeClassSpecified = true;
566 | }
567 | });
568 | }
569 | if (!sizeClassSpecified) {
570 | $button.removeClass(buttonSizes.join(' '));
571 | $button.addClass(dialog.getButtonSize());
572 | }
573 | });
574 | }
575 |
576 | return this;
577 | },
578 | getCssClass: function () {
579 | return this.options.cssClass;
580 | },
581 | setCssClass: function (cssClass) {
582 | this.options.cssClass = cssClass;
583 |
584 | return this;
585 | },
586 | getTitle: function () {
587 | return this.options.title;
588 | },
589 | setTitle: function (title) {
590 | this.options.title = title;
591 | this.updateTitle();
592 |
593 | return this;
594 | },
595 | updateTitle: function () {
596 | if (this.isRealized()) {
597 | var title = this.getTitle() !== null ? this.createDynamicContent(this.getTitle()) : this.getDefaultText();
598 | this.getModalHeader().find('.' + this.getNamespace('title')).html('').append(title).prop('id', this.getId() + '_title');
599 | }
600 |
601 | return this;
602 | },
603 | getMessage: function () {
604 | return this.options.message;
605 | },
606 | setMessage: function (message) {
607 | this.options.message = message;
608 | this.updateMessage();
609 |
610 | return this;
611 | },
612 | updateMessage: function () {
613 | if (this.isRealized()) {
614 | var message = this.createDynamicContent(this.getMessage());
615 | this.getModalBody().find('.' + this.getNamespace('message')).html('').append(message);
616 | }
617 |
618 | return this;
619 | },
620 | isClosable: function () {
621 | return this.options.closable;
622 | },
623 | setClosable: function (closable) {
624 | this.options.closable = closable;
625 | this.updateClosable();
626 |
627 | return this;
628 | },
629 | setCloseByBackdrop: function (closeByBackdrop) {
630 | this.options.closeByBackdrop = closeByBackdrop;
631 |
632 | return this;
633 | },
634 | canCloseByBackdrop: function () {
635 | return this.options.closeByBackdrop;
636 | },
637 | setCloseByKeyboard: function (closeByKeyboard) {
638 | this.options.closeByKeyboard = closeByKeyboard;
639 |
640 | return this;
641 | },
642 | canCloseByKeyboard: function () {
643 | return this.options.closeByKeyboard;
644 | },
645 | isAnimate: function () {
646 | return this.options.animate;
647 | },
648 | setAnimate: function (animate) {
649 | this.options.animate = animate;
650 |
651 | return this;
652 | },
653 | updateAnimate: function () {
654 | if (this.isRealized()) {
655 | this.getModal().toggleClass('fade', this.isAnimate());
656 | }
657 |
658 | return this;
659 | },
660 | getSpinicon: function () {
661 | return this.options.spinicon;
662 | },
663 | setSpinicon: function (spinicon) {
664 | this.options.spinicon = spinicon;
665 |
666 | return this;
667 | },
668 | addButton: function (button) {
669 | this.options.buttons.push(button);
670 |
671 | return this;
672 | },
673 | addButtons: function (buttons) {
674 | var that = this;
675 | $.each(buttons, function (index, button) {
676 | that.addButton(button);
677 | });
678 |
679 | return this;
680 | },
681 | getButtons: function () {
682 | return this.options.buttons;
683 | },
684 | setButtons: function (buttons) {
685 | this.options.buttons = buttons;
686 | this.updateButtons();
687 |
688 | return this;
689 | },
690 | /**
691 | * If there is id provided for a button option, it will be in dialog.indexedButtons list.
692 | *
693 | * In that case you can use dialog.getButton(id) to find the button.
694 | *
695 | * @param {type} id
696 | * @returns {undefined}
697 | */
698 | getButton: function (id) {
699 | if (typeof this.indexedButtons[id] !== 'undefined') {
700 | return this.indexedButtons[id];
701 | }
702 |
703 | return null;
704 | },
705 | getButtonSize: function () {
706 | if (typeof BootstrapDialog.BUTTON_SIZES[this.getSize()] !== 'undefined') {
707 | return BootstrapDialog.BUTTON_SIZES[this.getSize()];
708 | }
709 |
710 | return '';
711 | },
712 | updateButtons: function () {
713 | if (this.isRealized()) {
714 | if (this.getButtons().length === 0) {
715 | this.getModalFooter().hide();
716 | } else {
717 | this.getModalFooter().show().find('.' + this.getNamespace('footer')).html('').append(this.createFooterButtons());
718 | }
719 | }
720 |
721 | return this;
722 | },
723 | isAutodestroy: function () {
724 | return this.options.autodestroy;
725 | },
726 | setAutodestroy: function (autodestroy) {
727 | this.options.autodestroy = autodestroy;
728 | },
729 | getDescription: function () {
730 | return this.options.description;
731 | },
732 | setDescription: function (description) {
733 | this.options.description = description;
734 |
735 | return this;
736 | },
737 | setTabindex: function (tabindex) {
738 | this.options.tabindex = tabindex;
739 |
740 | return this;
741 | },
742 | getTabindex: function () {
743 | return this.options.tabindex;
744 | },
745 | updateTabindex: function () {
746 | if (this.isRealized()) {
747 | this.getModal().attr('tabindex', this.getTabindex());
748 | }
749 |
750 | return this;
751 | },
752 | getDefaultText: function () {
753 | return BootstrapDialog.DEFAULT_TEXTS[this.getType()];
754 | },
755 | getNamespace: function (name) {
756 | return BootstrapDialog.NAMESPACE + '-' + name;
757 | },
758 | createHeaderContent: function () {
759 | var $container = $('
');
760 | $container.addClass(this.getNamespace('header'));
761 |
762 | // title
763 | $container.append(this.createTitleContent());
764 |
765 | // Close button
766 | $container.prepend(this.createCloseButton());
767 |
768 | return $container;
769 | },
770 | createTitleContent: function () {
771 | var $title = $('
');
772 | $title.addClass(this.getNamespace('title'));
773 |
774 | return $title;
775 | },
776 | createCloseButton: function () {
777 | var $container = $('
');
778 | $container.addClass(this.getNamespace('close-button'));
779 | var $icon = $(' ');
780 | $icon.append(this.options.closeIcon);
781 | $container.append($icon);
782 | $container.on('click', {dialog: this}, function (event) {
783 | event.data.dialog.close();
784 | });
785 |
786 | return $container;
787 | },
788 | createBodyContent: function () {
789 | var $container = $('
');
790 | $container.addClass(this.getNamespace('body'));
791 |
792 | // Message
793 | $container.append(this.createMessageContent());
794 |
795 | return $container;
796 | },
797 | createMessageContent: function () {
798 | var $message = $('
');
799 | $message.addClass(this.getNamespace('message'));
800 |
801 | return $message;
802 | },
803 | createFooterContent: function () {
804 | var $container = $('
');
805 | $container.addClass(this.getNamespace('footer'));
806 |
807 | return $container;
808 | },
809 | createFooterButtons: function () {
810 | var that = this;
811 | var $container = $('
');
812 | $container.addClass(this.getNamespace('footer-buttons'));
813 | this.indexedButtons = {};
814 | $.each(this.options.buttons, function (index, button) {
815 | if (!button.id) {
816 | button.id = BootstrapDialog.newGuid();
817 | }
818 | var $button = that.createButton(button);
819 | that.indexedButtons[button.id] = $button;
820 | $container.append($button);
821 | });
822 |
823 | return $container;
824 | },
825 | createButton: function (button) {
826 | var $button = $(' ');
827 | $button.prop('id', button.id);
828 | $button.data('button', button);
829 |
830 | // Icon
831 | if (typeof button.icon !== 'undefined' && $.trim(button.icon) !== '') {
832 | $button.append(this.createButtonIcon(button.icon));
833 | }
834 |
835 | // Label
836 | if (typeof button.label !== 'undefined') {
837 | $button.append(button.label);
838 | }
839 |
840 | // title
841 | if (typeof button.title !== 'undefined') {
842 | $button.attr('title', button.title);
843 | }
844 |
845 | // Css class
846 | if (typeof button.cssClass !== 'undefined' && $.trim(button.cssClass) !== '') {
847 | $button.addClass(button.cssClass);
848 | } else {
849 | $button.addClass('btn-default');
850 | }
851 |
852 | // Data attributes
853 | if (typeof button.data === 'object' && button.data.constructor === {}.constructor) {
854 | $.each(button.data, function (key, value) {
855 | $button.attr('data-' + key, value);
856 | });
857 | }
858 |
859 | // Hotkey
860 | if (typeof button.hotkey !== 'undefined') {
861 | this.registeredButtonHotkeys[button.hotkey] = $button;
862 | }
863 |
864 | // Button on click
865 | $button.on('click', {dialog: this, $button: $button, button: button}, function (event) {
866 | var dialog = event.data.dialog;
867 | var $button = event.data.$button;
868 | var button = $button.data('button');
869 | if (button.autospin) {
870 | $button.toggleSpin(true);
871 | }
872 | if (typeof button.action === 'function') {
873 | return button.action.call($button, dialog, event);
874 | }
875 | });
876 |
877 | // Dynamically add extra functions to $button
878 | this.enhanceButton($button);
879 |
880 | //Initialize enabled or not
881 | if (typeof button.enabled !== 'undefined') {
882 | $button.toggleEnable(button.enabled);
883 | }
884 |
885 | return $button;
886 | },
887 | /**
888 | * Dynamically add extra functions to $button
889 | *
890 | * Using '$this' to reference 'this' is just for better readability.
891 | *
892 | * @param {type} $button
893 | * @returns {_L13.BootstrapDialog.prototype}
894 | */
895 | enhanceButton: function ($button) {
896 | $button.dialog = this;
897 |
898 | // Enable / Disable
899 | $button.toggleEnable = function (enable) {
900 | var $this = this;
901 | if (typeof enable !== 'undefined') {
902 | $this.prop("disabled", !enable).toggleClass('disabled', !enable);
903 | } else {
904 | $this.prop("disabled", !$this.prop("disabled"));
905 | }
906 |
907 | return $this;
908 | };
909 | $button.enable = function () {
910 | var $this = this;
911 | $this.toggleEnable(true);
912 |
913 | return $this;
914 | };
915 | $button.disable = function () {
916 | var $this = this;
917 | $this.toggleEnable(false);
918 |
919 | return $this;
920 | };
921 |
922 | // Icon spinning, helpful for indicating ajax loading status.
923 | $button.toggleSpin = function (spin) {
924 | var $this = this;
925 | var dialog = $this.dialog;
926 | var $icon = $this.find('.' + dialog.getNamespace('button-icon'));
927 | if (typeof spin === 'undefined') {
928 | spin = !($button.find('.icon-spin').length > 0);
929 | }
930 | if (spin) {
931 | $icon.hide();
932 | $button.prepend(dialog.createButtonIcon(dialog.getSpinicon()).addClass('icon-spin'));
933 | } else {
934 | $icon.show();
935 | $button.find('.icon-spin').remove();
936 | }
937 |
938 | return $this;
939 | };
940 | $button.spin = function () {
941 | var $this = this;
942 | $this.toggleSpin(true);
943 |
944 | return $this;
945 | };
946 | $button.stopSpin = function () {
947 | var $this = this;
948 | $this.toggleSpin(false);
949 |
950 | return $this;
951 | };
952 |
953 | return this;
954 | },
955 | createButtonIcon: function (icon) {
956 | var $icon = $(' ');
957 | $icon.addClass(this.getNamespace('button-icon')).addClass(icon);
958 |
959 | return $icon;
960 | },
961 | /**
962 | * Invoke this only after the dialog is realized.
963 | *
964 | * @param {type} enable
965 | * @returns {undefined}
966 | */
967 | enableButtons: function (enable) {
968 | $.each(this.indexedButtons, function (id, $button) {
969 | $button.toggleEnable(enable);
970 | });
971 |
972 | return this;
973 | },
974 | /**
975 | * Invoke this only after the dialog is realized.
976 | *
977 | * @returns {undefined}
978 | */
979 | updateClosable: function () {
980 | if (this.isRealized()) {
981 | // Close button
982 | this.getModalHeader().find('.' + this.getNamespace('close-button')).toggle(this.isClosable());
983 | }
984 |
985 | return this;
986 | },
987 | /**
988 | * Set handler for modal event 'show.bs.modal'.
989 | * This is a setter!
990 | */
991 | onShow: function (onshow) {
992 | this.options.onshow = onshow;
993 |
994 | return this;
995 | },
996 | /**
997 | * Set handler for modal event 'shown.bs.modal'.
998 | * This is a setter!
999 | */
1000 | onShown: function (onshown) {
1001 | this.options.onshown = onshown;
1002 |
1003 | return this;
1004 | },
1005 | /**
1006 | * Set handler for modal event 'hide.bs.modal'.
1007 | * This is a setter!
1008 | */
1009 | onHide: function (onhide) {
1010 | this.options.onhide = onhide;
1011 |
1012 | return this;
1013 | },
1014 | /**
1015 | * Set handler for modal event 'hidden.bs.modal'.
1016 | * This is a setter!
1017 | */
1018 | onHidden: function (onhidden) {
1019 | this.options.onhidden = onhidden;
1020 |
1021 | return this;
1022 | },
1023 | isRealized: function () {
1024 | return this.realized;
1025 | },
1026 | setRealized: function (realized) {
1027 | this.realized = realized;
1028 |
1029 | return this;
1030 | },
1031 | isOpened: function () {
1032 | return this.opened;
1033 | },
1034 | setOpened: function (opened) {
1035 | this.opened = opened;
1036 |
1037 | return this;
1038 | },
1039 | handleModalEvents: function () {
1040 | this.getModal().on('show.bs.modal', {dialog: this}, function (event) {
1041 | var dialog = event.data.dialog;
1042 | dialog.setOpened(true);
1043 | if (dialog.isModalEvent(event) && typeof dialog.options.onshow === 'function') {
1044 | var openIt = dialog.options.onshow(dialog);
1045 | if (openIt === false) {
1046 | dialog.setOpened(false);
1047 | }
1048 |
1049 | return openIt;
1050 | }
1051 | });
1052 | this.getModal().on('shown.bs.modal', {dialog: this}, function (event) {
1053 | var dialog = event.data.dialog;
1054 | dialog.isModalEvent(event) && typeof dialog.options.onshown === 'function' && dialog.options.onshown(dialog);
1055 | });
1056 | this.getModal().on('hide.bs.modal', {dialog: this}, function (event) {
1057 | var dialog = event.data.dialog;
1058 | dialog.setOpened(false);
1059 | if (dialog.isModalEvent(event) && typeof dialog.options.onhide === 'function') {
1060 | var hideIt = dialog.options.onhide(dialog);
1061 | if (hideIt === false) {
1062 | dialog.setOpened(true);
1063 | }
1064 |
1065 | return hideIt;
1066 | }
1067 | });
1068 | this.getModal().on('hidden.bs.modal', {dialog: this}, function (event) {
1069 | var dialog = event.data.dialog;
1070 | dialog.isModalEvent(event) && typeof dialog.options.onhidden === 'function' && dialog.options.onhidden(dialog);
1071 | if (dialog.isAutodestroy()) {
1072 | dialog.setRealized(false);
1073 | delete BootstrapDialog.dialogs[dialog.getId()];
1074 | $(this).remove();
1075 | }
1076 | BootstrapDialog.moveFocus();
1077 | if ($('.modal').hasClass('in')) {
1078 | $('body').addClass('modal-open');
1079 | }
1080 | });
1081 |
1082 | // Backdrop, I did't find a way to change bs3 backdrop option after the dialog is popped up, so here's a new wheel.
1083 | this.handleModalBackdropEvent();
1084 |
1085 | // ESC key support
1086 | this.getModal().on('keyup', {dialog: this}, function (event) {
1087 | event.which === 27 && event.data.dialog.isClosable() && event.data.dialog.canCloseByKeyboard() && event.data.dialog.close();
1088 | });
1089 |
1090 | // Button hotkey
1091 | this.getModal().on('keyup', {dialog: this}, function (event) {
1092 | var dialog = event.data.dialog;
1093 | if (typeof dialog.registeredButtonHotkeys[event.which] !== 'undefined') {
1094 | var $button = $(dialog.registeredButtonHotkeys[event.which]);
1095 | !$button.prop('disabled') && !$button.is(':focus') && $button.focus().trigger('click');
1096 | }
1097 | });
1098 |
1099 | return this;
1100 | },
1101 | handleModalBackdropEvent: function () {
1102 | this.getModal().on('click', {dialog: this}, function (event) {
1103 | $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
1104 | });
1105 |
1106 | return this;
1107 | },
1108 | isModalEvent: function (event) {
1109 | return typeof event.namespace !== 'undefined' && event.namespace === 'bs.modal';
1110 | },
1111 | makeModalDraggable: function () {
1112 | if (this.options.draggable) {
1113 | this.getModalHeader().addClass(this.getNamespace('draggable')).on('mousedown', {dialog: this}, function (event) {
1114 | var dialog = event.data.dialog;
1115 | dialog.draggableData.isMouseDown = true;
1116 | var dialogOffset = dialog.getModalDialog().offset();
1117 | dialog.draggableData.mouseOffset = {
1118 | top: event.clientY - dialogOffset.top,
1119 | left: event.clientX - dialogOffset.left
1120 | };
1121 | });
1122 | this.getModal().on('mouseup mouseleave', {dialog: this}, function (event) {
1123 | event.data.dialog.draggableData.isMouseDown = false;
1124 | });
1125 | $('body').on('mousemove', {dialog: this}, function (event) {
1126 | var dialog = event.data.dialog;
1127 | if (!dialog.draggableData.isMouseDown) {
1128 | return;
1129 | }
1130 | dialog.getModalDialog().offset({
1131 | top: event.clientY - dialog.draggableData.mouseOffset.top,
1132 | left: event.clientX - dialog.draggableData.mouseOffset.left
1133 | });
1134 | });
1135 | }
1136 |
1137 | return this;
1138 | },
1139 | realize: function () {
1140 | this.initModalStuff();
1141 | this.getModal().addClass(BootstrapDialog.NAMESPACE)
1142 | .addClass(this.getCssClass());
1143 | this.updateSize();
1144 | if (this.getDescription()) {
1145 | this.getModal().attr('aria-describedby', this.getDescription());
1146 | }
1147 | this.getModalFooter().append(this.createFooterContent());
1148 | this.getModalHeader().append(this.createHeaderContent());
1149 | this.getModalBody().append(this.createBodyContent());
1150 | this.getModal().data('bs.modal', new BootstrapDialogModal(this.getModal(), {
1151 | backdrop: 'static',
1152 | keyboard: false,
1153 | show: false
1154 | }));
1155 | this.makeModalDraggable();
1156 | this.handleModalEvents();
1157 | this.setRealized(true);
1158 | this.updateButtons();
1159 | this.updateType();
1160 | this.updateTitle();
1161 | this.updateMessage();
1162 | this.updateClosable();
1163 | this.updateAnimate();
1164 | this.updateSize();
1165 | this.updateTabindex();
1166 |
1167 | return this;
1168 | },
1169 | open: function () {
1170 | !this.isRealized() && this.realize();
1171 | this.getModal().modal('show');
1172 |
1173 | return this;
1174 | },
1175 | close: function () {
1176 | !this.isRealized() && this.realize();
1177 | this.getModal().modal('hide');
1178 |
1179 | return this;
1180 | }
1181 | };
1182 |
1183 | // Add compatible methods.
1184 | BootstrapDialog.prototype = $.extend(BootstrapDialog.prototype, BootstrapDialog.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
1185 |
1186 | /**
1187 | * RFC4122 version 4 compliant unique id creator.
1188 | *
1189 | * Added by https://github.com/tufanbarisyildirim/
1190 | *
1191 | * @returns {String}
1192 | */
1193 | BootstrapDialog.newGuid = function () {
1194 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
1195 | var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
1196 | return v.toString(16);
1197 | });
1198 | };
1199 |
1200 | /* ================================================
1201 | * For lazy people
1202 | * ================================================ */
1203 |
1204 | /**
1205 | * Shortcut function: show
1206 | *
1207 | * @param {type} options
1208 | * @returns the created dialog instance
1209 | */
1210 | BootstrapDialog.show = function (options) {
1211 | return new BootstrapDialog(options).open();
1212 | };
1213 |
1214 | /**
1215 | * Alert window
1216 | *
1217 | * @returns the created dialog instance
1218 | */
1219 | BootstrapDialog.alert = function () {
1220 | var alertOptions = {};
1221 | var defaultAlertOptions = {
1222 | type: BootstrapDialog.TYPE_PRIMARY,
1223 | title: null,
1224 | message: null,
1225 | closable: false,
1226 | draggable: false,
1227 | buttonLabel: BootstrapDialog.DEFAULT_TEXTS.OK,
1228 | buttonHotkey: null,
1229 | callback: null
1230 | };
1231 |
1232 | if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
1233 | alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
1234 | } else {
1235 | alertOptions = $.extend(true, defaultAlertOptions, {
1236 | message: arguments[0],
1237 | callback: typeof arguments[1] !== 'undefined' ? arguments[1] : null
1238 | });
1239 | }
1240 |
1241 | var dialog = new BootstrapDialog(alertOptions);
1242 | dialog.setData('callback', alertOptions.callback);
1243 | dialog.addButton({
1244 | label: alertOptions.buttonLabel,
1245 | hotkey: alertOptions.buttonHotkey,
1246 | action: function (dialog) {
1247 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, true) === false) {
1248 | return false;
1249 | }
1250 | dialog.setData('btnClicked', true);
1251 |
1252 | return dialog.close();
1253 | }
1254 | });
1255 | if (typeof dialog.options.onhide === 'function') {
1256 | dialog.onHide(function (dialog) {
1257 | var hideIt = true;
1258 | if (!dialog.getData('btnClicked') && dialog.isClosable() && typeof dialog.getData('callback') === 'function') {
1259 | hideIt = dialog.getData('callback')(false);
1260 | }
1261 | if (hideIt === false) {
1262 | return false;
1263 | }
1264 | hideIt = this.onhide(dialog);
1265 |
1266 | return hideIt;
1267 | }.bind({
1268 | onhide: dialog.options.onhide
1269 | }));
1270 | } else {
1271 | dialog.onHide(function (dialog) {
1272 | var hideIt = true;
1273 | if (!dialog.getData('btnClicked') && dialog.isClosable() && typeof dialog.getData('callback') === 'function') {
1274 | hideIt = dialog.getData('callback')(false);
1275 | }
1276 |
1277 | return hideIt;
1278 | });
1279 | }
1280 |
1281 | return dialog.open();
1282 | };
1283 |
1284 | /**
1285 | * Confirm window
1286 | *
1287 | * @returns the created dialog instance
1288 | */
1289 | BootstrapDialog.confirm = function () {
1290 | var confirmOptions = {};
1291 | var defaultConfirmOptions = {
1292 | type: BootstrapDialog.TYPE_PRIMARY,
1293 | title: null,
1294 | message: null,
1295 | closable: false,
1296 | draggable: false,
1297 | btnCancelLabel: BootstrapDialog.DEFAULT_TEXTS.CANCEL,
1298 | btnCancelClass: null,
1299 | btnCancelHotkey: null,
1300 | btnOKLabel: BootstrapDialog.DEFAULT_TEXTS.OK,
1301 | btnOKClass: null,
1302 | btnOKHotkey: null,
1303 | btnsOrder: BootstrapDialog.defaultOptions.btnsOrder,
1304 | callback: null
1305 | };
1306 | if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
1307 | confirmOptions = $.extend(true, defaultConfirmOptions, arguments[0]);
1308 | } else {
1309 | confirmOptions = $.extend(true, defaultConfirmOptions, {
1310 | message: arguments[0],
1311 | callback: typeof arguments[1] !== 'undefined' ? arguments[1] : null
1312 | });
1313 | }
1314 | if (confirmOptions.btnOKClass === null) {
1315 | confirmOptions.btnOKClass = ['btn', confirmOptions.type.split('-')[1]].join('-');
1316 | }
1317 |
1318 | var dialog = new BootstrapDialog(confirmOptions);
1319 | dialog.setData('callback', confirmOptions.callback);
1320 |
1321 | var buttons = [{
1322 | label: confirmOptions.btnCancelLabel,
1323 | cssClass: confirmOptions.btnCancelClass,
1324 | hotkey: confirmOptions.btnCancelHotkey,
1325 | action: function (dialog) {
1326 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, false) === false) {
1327 | return false;
1328 | }
1329 |
1330 | return dialog.close();
1331 | }
1332 | }, {
1333 | label: confirmOptions.btnOKLabel,
1334 | cssClass: confirmOptions.btnOKClass,
1335 | hotkey: confirmOptions.btnOKHotkey,
1336 | action: function (dialog) {
1337 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, true) === false) {
1338 | return false;
1339 | }
1340 |
1341 | return dialog.close();
1342 | }
1343 | }];
1344 | if (confirmOptions.btnsOrder === BootstrapDialog.BUTTONS_ORDER_OK_CANCEL) {
1345 | buttons.reverse();
1346 | }
1347 | dialog.addButtons(buttons);
1348 |
1349 | return dialog.open();
1350 |
1351 | };
1352 |
1353 | /**
1354 | * Warning window
1355 | *
1356 | * @param {type} message
1357 | * @returns the created dialog instance
1358 | */
1359 | BootstrapDialog.warning = function (message, callback) {
1360 | return new BootstrapDialog({
1361 | type: BootstrapDialog.TYPE_WARNING,
1362 | message: message
1363 | }).open();
1364 | };
1365 |
1366 | /**
1367 | * Danger window
1368 | *
1369 | * @param {type} message
1370 | * @returns the created dialog instance
1371 | */
1372 | BootstrapDialog.danger = function (message, callback) {
1373 | return new BootstrapDialog({
1374 | type: BootstrapDialog.TYPE_DANGER,
1375 | message: message
1376 | }).open();
1377 | };
1378 |
1379 | /**
1380 | * Success window
1381 | *
1382 | * @param {type} message
1383 | * @returns the created dialog instance
1384 | */
1385 | BootstrapDialog.success = function (message, callback) {
1386 | return new BootstrapDialog({
1387 | type: BootstrapDialog.TYPE_SUCCESS,
1388 | message: message
1389 | }).open();
1390 | };
1391 |
1392 | return BootstrapDialog;
1393 |
1394 | }));
1395 |
--------------------------------------------------------------------------------
/dist/js/bootstrap-dialog.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"use strict";"undefined"!=typeof module&&module.exports?module.exports=e(require("jquery"),require("bootstrap")):"function"==typeof define&&define.amd?define("bootstrap-dialog",["jquery","bootstrap"],function(t){return e(t)}):t.BootstrapDialog=e(t.jQuery)}(this,function(t){"use strict";var e=t.fn.modal.Constructor,n=function(t,n){e.call(this,t,n)};n.getModalVersion=function(){return void 0===t.fn.modal.Constructor.VERSION?"v3.1":/3\.2\.\d+/.test(t.fn.modal.Constructor.VERSION)?"v3.2":/3\.3\.[1,2]/.test(t.fn.modal.Constructor.VERSION)?"v3.3":"v3.3.4"},n.ORIGINAL_BODY_PADDING=parseInt(t("body").css("padding-right")||0,10),(n.METHODS_TO_OVERRIDE={})["v3.1"]={},n.METHODS_TO_OVERRIDE["v3.2"]={hide:function(e){e&&e.preventDefault(),e=t.Event("hide.bs.modal"),this.$element.trigger(e),this.isShown&&!e.isDefaultPrevented()&&(this.isShown=!1,0===this.getGlobalOpenedDialogs().length&&this.$body.removeClass("modal-open"),this.resetScrollbar(),this.escape(),t(document).off("focusin.bs.modal"),this.$element.removeClass("in").attr("aria-hidden",!0).off("click.dismiss.bs.modal"),t.support.transition&&this.$element.hasClass("fade")?this.$element.one("bsTransitionEnd",t.proxy(this.hideModal,this)).emulateTransitionEnd(300):this.hideModal())}},n.METHODS_TO_OVERRIDE["v3.3"]={setScrollbar:function(){var t=n.ORIGINAL_BODY_PADDING;this.bodyIsOverflowing&&this.$body.css("padding-right",t+this.scrollbarWidth)},resetScrollbar:function(){0===this.getGlobalOpenedDialogs().length&&this.$body.css("padding-right",n.ORIGINAL_BODY_PADDING)},hideModal:function(){this.$element.hide(),this.backdrop(t.proxy(function(){0===this.getGlobalOpenedDialogs().length&&this.$body.removeClass("modal-open"),this.resetAdjustments(),this.resetScrollbar(),this.$element.trigger("hidden.bs.modal")},this))}},n.METHODS_TO_OVERRIDE["v3.3.4"]=t.extend({},n.METHODS_TO_OVERRIDE["v3.3"]),n.prototype={constructor:n,getGlobalOpenedDialogs:function(){var e=[];return t.each(o.dialogs,function(t,n){n.isRealized()&&n.isOpened()&&e.push(n)}),e}},n.prototype=t.extend(n.prototype,e.prototype,n.METHODS_TO_OVERRIDE[n.getModalVersion()]);var o=function(e){this.defaultOptions=t.extend(!0,{id:o.newGuid(),buttons:[],data:{},onshow:null,onshown:null,onhide:null,onhidden:null},o.defaultOptions),this.indexedButtons={},this.registeredButtonHotkeys={},this.draggableData={isMouseDown:!1,mouseOffset:{}},this.realized=!1,this.opened=!1,this.initOptions(e),this.holdThisInstance()};return o.BootstrapDialogModal=n,o.NAMESPACE="bootstrap-dialog",o.TYPE_DEFAULT="type-default",o.TYPE_INFO="type-info",o.TYPE_PRIMARY="type-primary",o.TYPE_SUCCESS="type-success",o.TYPE_WARNING="type-warning",o.TYPE_DANGER="type-danger",o.DEFAULT_TEXTS={},o.DEFAULT_TEXTS[o.TYPE_DEFAULT]="Information",o.DEFAULT_TEXTS[o.TYPE_INFO]="Information",o.DEFAULT_TEXTS[o.TYPE_PRIMARY]="Information",o.DEFAULT_TEXTS[o.TYPE_SUCCESS]="Success",o.DEFAULT_TEXTS[o.TYPE_WARNING]="Warning",o.DEFAULT_TEXTS[o.TYPE_DANGER]="Danger",o.DEFAULT_TEXTS.OK="OK",o.DEFAULT_TEXTS.CANCEL="Cancel",o.DEFAULT_TEXTS.CONFIRM="Confirmation",o.SIZE_NORMAL="size-normal",o.SIZE_SMALL="size-small",o.SIZE_WIDE="size-wide",o.SIZE_LARGE="size-large",o.BUTTON_SIZES={},o.BUTTON_SIZES[o.SIZE_NORMAL]="",o.BUTTON_SIZES[o.SIZE_SMALL]="",o.BUTTON_SIZES[o.SIZE_WIDE]="",o.BUTTON_SIZES[o.SIZE_LARGE]="btn-lg",o.ICON_SPINNER="glyphicon glyphicon-asterisk",o.BUTTONS_ORDER_CANCEL_OK="btns-order-cancel-ok",o.BUTTONS_ORDER_OK_CANCEL="btns-order-ok-cancel",o.defaultOptions={type:o.TYPE_PRIMARY,size:o.SIZE_NORMAL,cssClass:"",title:null,message:null,nl2br:!0,closable:!0,closeByBackdrop:!0,closeByKeyboard:!0,closeIcon:"×",spinicon:o.ICON_SPINNER,autodestroy:!0,draggable:!1,animate:!0,description:"",tabindex:-1,btnsOrder:o.BUTTONS_ORDER_CANCEL_OK},o.configDefaultOptions=function(e){o.defaultOptions=t.extend(!0,o.defaultOptions,e)},o.dialogs={},o.openAll=function(){t.each(o.dialogs,function(t,e){e.open()})},o.closeAll=function(){t.each(o.dialogs,function(t,e){e.close()})},o.getDialog=function(t){var e=null;return void 0!==o.dialogs[t]&&(e=o.dialogs[t]),e},o.setDialog=function(t){return o.dialogs[t.getId()]=t,t},o.addDialog=function(t){return o.setDialog(t)},o.moveFocus=function(){var e=null;t.each(o.dialogs,function(t,n){n.isRealized()&&n.isOpened()&&(e=n)}),null!==e&&e.getModal().focus()},o.METHODS_TO_OVERRIDE={},o.METHODS_TO_OVERRIDE["v3.1"]={handleModalBackdropEvent:function(){return this.getModal().on("click",{dialog:this},function(t){t.target===this&&t.data.dialog.isClosable()&&t.data.dialog.canCloseByBackdrop()&&t.data.dialog.close()}),this},updateZIndex:function(){if(this.isOpened()){var e=0;t.each(o.dialogs,function(t,n){n.isRealized()&&n.isOpened()&&e++});var n=this.getModal(),i=n.data("bs.modal").$backdrop;n.css("z-index",1050+20*(e-1)),i.css("z-index",1040+20*(e-1))}return this},open:function(){return!this.isRealized()&&this.realize(),this.getModal().modal("show"),this.updateZIndex(),this}},o.METHODS_TO_OVERRIDE["v3.2"]={handleModalBackdropEvent:o.METHODS_TO_OVERRIDE["v3.1"].handleModalBackdropEvent,updateZIndex:o.METHODS_TO_OVERRIDE["v3.1"].updateZIndex,open:o.METHODS_TO_OVERRIDE["v3.1"].open},o.METHODS_TO_OVERRIDE["v3.3"]={},o.METHODS_TO_OVERRIDE["v3.3.4"]=t.extend({},o.METHODS_TO_OVERRIDE["v3.1"]),o.prototype={constructor:o,initOptions:function(e){return this.options=t.extend(!0,this.defaultOptions,e),this},holdThisInstance:function(){return o.addDialog(this),this},initModalStuff:function(){return this.setModal(this.createModal()).setModalDialog(this.createModalDialog()).setModalContent(this.createModalContent()).setModalHeader(this.createModalHeader()).setModalBody(this.createModalBody()).setModalFooter(this.createModalFooter()),this.getModal().append(this.getModalDialog()),this.getModalDialog().append(this.getModalContent()),this.getModalContent().append(this.getModalHeader()).append(this.getModalBody()).append(this.getModalFooter()),this},createModal:function(){var e=t('
');return e.prop("id",this.getId()),e.attr("aria-labelledby",this.getId()+"_title"),e},getModal:function(){return this.$modal},setModal:function(t){return this.$modal=t,this},createModalDialog:function(){return t('
')},getModalDialog:function(){return this.$modalDialog},setModalDialog:function(t){return this.$modalDialog=t,this},createModalContent:function(){return t('
')},getModalContent:function(){return this.$modalContent},setModalContent:function(t){return this.$modalContent=t,this},createModalHeader:function(){return t('')},getModalHeader:function(){return this.$modalHeader},setModalHeader:function(t){return this.$modalHeader=t,this},createModalBody:function(){return t('
')},getModalBody:function(){return this.$modalBody},setModalBody:function(t){return this.$modalBody=t,this},createModalFooter:function(){return t('')},getModalFooter:function(){return this.$modalFooter},setModalFooter:function(t){return this.$modalFooter=t,this},createDynamicContent:function(t){var e=null;return"string"==typeof(e="function"==typeof t?t.call(t,this):t)&&(e=this.formatStringContent(e)),e},formatStringContent:function(t){return this.options.nl2br?t.replace(/\r\n/g," ").replace(/[\r\n]/g," "):t},setData:function(t,e){return this.options.data[t]=e,this},getData:function(t){return this.options.data[t]},setId:function(t){return this.options.id=t,this},getId:function(){return this.options.id},getType:function(){return this.options.type},setType:function(t){return this.options.type=t,this.updateType(),this},updateType:function(){if(this.isRealized()){var t=[o.TYPE_DEFAULT,o.TYPE_INFO,o.TYPE_PRIMARY,o.TYPE_SUCCESS,o.TYPE_WARNING,o.TYPE_DANGER];this.getModal().removeClass(t.join(" ")).addClass(this.getType())}return this},getSize:function(){return this.options.size},setSize:function(t){return this.options.size=t,this.updateSize(),this},updateSize:function(){if(this.isRealized()){var e=this;this.getModal().removeClass(o.SIZE_NORMAL).removeClass(o.SIZE_SMALL).removeClass(o.SIZE_WIDE).removeClass(o.SIZE_LARGE),this.getModal().addClass(this.getSize()),this.getModalDialog().removeClass("modal-sm"),this.getSize()===o.SIZE_SMALL&&this.getModalDialog().addClass("modal-sm"),this.getModalDialog().removeClass("modal-lg"),this.getSize()===o.SIZE_WIDE&&this.getModalDialog().addClass("modal-lg"),t.each(this.options.buttons,function(n,o){var i=e.getButton(o.id),s=["btn-lg","btn-sm","btn-xs"],a=!1;if("string"==typeof o.cssClass){var d=o.cssClass.split(" ");t.each(d,function(e,n){-1!==t.inArray(n,s)&&(a=!0)})}a||(i.removeClass(s.join(" ")),i.addClass(e.getButtonSize()))})}return this},getCssClass:function(){return this.options.cssClass},setCssClass:function(t){return this.options.cssClass=t,this},getTitle:function(){return this.options.title},setTitle:function(t){return this.options.title=t,this.updateTitle(),this},updateTitle:function(){if(this.isRealized()){var t=null!==this.getTitle()?this.createDynamicContent(this.getTitle()):this.getDefaultText();this.getModalHeader().find("."+this.getNamespace("title")).html("").append(t).prop("id",this.getId()+"_title")}return this},getMessage:function(){return this.options.message},setMessage:function(t){return this.options.message=t,this.updateMessage(),this},updateMessage:function(){if(this.isRealized()){var t=this.createDynamicContent(this.getMessage());this.getModalBody().find("."+this.getNamespace("message")).html("").append(t)}return this},isClosable:function(){return this.options.closable},setClosable:function(t){return this.options.closable=t,this.updateClosable(),this},setCloseByBackdrop:function(t){return this.options.closeByBackdrop=t,this},canCloseByBackdrop:function(){return this.options.closeByBackdrop},setCloseByKeyboard:function(t){return this.options.closeByKeyboard=t,this},canCloseByKeyboard:function(){return this.options.closeByKeyboard},isAnimate:function(){return this.options.animate},setAnimate:function(t){return this.options.animate=t,this},updateAnimate:function(){return this.isRealized()&&this.getModal().toggleClass("fade",this.isAnimate()),this},getSpinicon:function(){return this.options.spinicon},setSpinicon:function(t){return this.options.spinicon=t,this},addButton:function(t){return this.options.buttons.push(t),this},addButtons:function(e){var n=this;return t.each(e,function(t,e){n.addButton(e)}),this},getButtons:function(){return this.options.buttons},setButtons:function(t){return this.options.buttons=t,this.updateButtons(),this},getButton:function(t){return void 0!==this.indexedButtons[t]?this.indexedButtons[t]:null},getButtonSize:function(){return void 0!==o.BUTTON_SIZES[this.getSize()]?o.BUTTON_SIZES[this.getSize()]:""},updateButtons:function(){return this.isRealized()&&(0===this.getButtons().length?this.getModalFooter().hide():this.getModalFooter().show().find("."+this.getNamespace("footer")).html("").append(this.createFooterButtons())),this},isAutodestroy:function(){return this.options.autodestroy},setAutodestroy:function(t){this.options.autodestroy=t},getDescription:function(){return this.options.description},setDescription:function(t){return this.options.description=t,this},setTabindex:function(t){return this.options.tabindex=t,this},getTabindex:function(){return this.options.tabindex},updateTabindex:function(){return this.isRealized()&&this.getModal().attr("tabindex",this.getTabindex()),this},getDefaultText:function(){return o.DEFAULT_TEXTS[this.getType()]},getNamespace:function(t){return o.NAMESPACE+"-"+t},createHeaderContent:function(){var e=t("
");return e.addClass(this.getNamespace("header")),e.append(this.createTitleContent()),e.prepend(this.createCloseButton()),e},createTitleContent:function(){var e=t("
");return e.addClass(this.getNamespace("title")),e},createCloseButton:function(){var e=t("
");e.addClass(this.getNamespace("close-button"));var n=t(' ');return n.append(this.options.closeIcon),e.append(n),e.on("click",{dialog:this},function(t){t.data.dialog.close()}),e},createBodyContent:function(){var e=t("
");return e.addClass(this.getNamespace("body")),e.append(this.createMessageContent()),e},createMessageContent:function(){var e=t("
");return e.addClass(this.getNamespace("message")),e},createFooterContent:function(){var e=t("
");return e.addClass(this.getNamespace("footer")),e},createFooterButtons:function(){var e=this,n=t("
");return n.addClass(this.getNamespace("footer-buttons")),this.indexedButtons={},t.each(this.options.buttons,function(t,i){i.id||(i.id=o.newGuid());var s=e.createButton(i);e.indexedButtons[i.id]=s,n.append(s)}),n},createButton:function(e){var n=t(' ');return n.prop("id",e.id),n.data("button",e),void 0!==e.icon&&""!==t.trim(e.icon)&&n.append(this.createButtonIcon(e.icon)),void 0!==e.label&&n.append(e.label),void 0!==e.title&&n.attr("title",e.title),void 0!==e.cssClass&&""!==t.trim(e.cssClass)?n.addClass(e.cssClass):n.addClass("btn-default"),"object"==typeof e.data&&e.data.constructor==={}.constructor&&t.each(e.data,function(t,e){n.attr("data-"+t,e)}),void 0!==e.hotkey&&(this.registeredButtonHotkeys[e.hotkey]=n),n.on("click",{dialog:this,$button:n,button:e},function(t){var e=t.data.dialog,n=t.data.$button,o=n.data("button");if(o.autospin&&n.toggleSpin(!0),"function"==typeof o.action)return o.action.call(n,e,t)}),this.enhanceButton(n),void 0!==e.enabled&&n.toggleEnable(e.enabled),n},enhanceButton:function(t){return t.dialog=this,t.toggleEnable=function(t){var e=this;return void 0!==t?e.prop("disabled",!t).toggleClass("disabled",!t):e.prop("disabled",!e.prop("disabled")),e},t.enable=function(){var t=this;return t.toggleEnable(!0),t},t.disable=function(){var t=this;return t.toggleEnable(!1),t},t.toggleSpin=function(e){var n=this,o=n.dialog,i=n.find("."+o.getNamespace("button-icon"));return void 0===e&&(e=!(t.find(".icon-spin").length>0)),e?(i.hide(),t.prepend(o.createButtonIcon(o.getSpinicon()).addClass("icon-spin"))):(i.show(),t.find(".icon-spin").remove()),n},t.spin=function(){var t=this;return t.toggleSpin(!0),t},t.stopSpin=function(){var t=this;return t.toggleSpin(!1),t},this},createButtonIcon:function(e){var n=t(" ");return n.addClass(this.getNamespace("button-icon")).addClass(e),n},enableButtons:function(e){return t.each(this.indexedButtons,function(t,n){n.toggleEnable(e)}),this},updateClosable:function(){return this.isRealized()&&this.getModalHeader().find("."+this.getNamespace("close-button")).toggle(this.isClosable()),this},onShow:function(t){return this.options.onshow=t,this},onShown:function(t){return this.options.onshown=t,this},onHide:function(t){return this.options.onhide=t,this},onHidden:function(t){return this.options.onhidden=t,this},isRealized:function(){return this.realized},setRealized:function(t){return this.realized=t,this},isOpened:function(){return this.opened},setOpened:function(t){return this.opened=t,this},handleModalEvents:function(){return this.getModal().on("show.bs.modal",{dialog:this},function(t){var e=t.data.dialog;if(e.setOpened(!0),e.isModalEvent(t)&&"function"==typeof e.options.onshow){var n=e.options.onshow(e);return!1===n&&e.setOpened(!1),n}}),this.getModal().on("shown.bs.modal",{dialog:this},function(t){var e=t.data.dialog;e.isModalEvent(t)&&"function"==typeof e.options.onshown&&e.options.onshown(e)}),this.getModal().on("hide.bs.modal",{dialog:this},function(t){var e=t.data.dialog;if(e.setOpened(!1),e.isModalEvent(t)&&"function"==typeof e.options.onhide){var n=e.options.onhide(e);return!1===n&&e.setOpened(!0),n}}),this.getModal().on("hidden.bs.modal",{dialog:this},function(e){var n=e.data.dialog;n.isModalEvent(e)&&"function"==typeof n.options.onhidden&&n.options.onhidden(n),n.isAutodestroy()&&(n.setRealized(!1),delete o.dialogs[n.getId()],t(this).remove()),o.moveFocus(),t(".modal").hasClass("in")&&t("body").addClass("modal-open")}),this.handleModalBackdropEvent(),this.getModal().on("keyup",{dialog:this},function(t){27===t.which&&t.data.dialog.isClosable()&&t.data.dialog.canCloseByKeyboard()&&t.data.dialog.close()}),this.getModal().on("keyup",{dialog:this},function(e){var n=e.data.dialog;if(void 0!==n.registeredButtonHotkeys[e.which]){var o=t(n.registeredButtonHotkeys[e.which]);!o.prop("disabled")&&!o.is(":focus")&&o.focus().trigger("click")}}),this},handleModalBackdropEvent:function(){return this.getModal().on("click",{dialog:this},function(e){t(e.target).hasClass("modal-backdrop")&&e.data.dialog.isClosable()&&e.data.dialog.canCloseByBackdrop()&&e.data.dialog.close()}),this},isModalEvent:function(t){return void 0!==t.namespace&&"bs.modal"===t.namespace},makeModalDraggable:function(){return this.options.draggable&&(this.getModalHeader().addClass(this.getNamespace("draggable")).on("mousedown",{dialog:this},function(t){var e=t.data.dialog;e.draggableData.isMouseDown=!0;var n=e.getModalDialog().offset();e.draggableData.mouseOffset={top:t.clientY-n.top,left:t.clientX-n.left}}),this.getModal().on("mouseup mouseleave",{dialog:this},function(t){t.data.dialog.draggableData.isMouseDown=!1}),t("body").on("mousemove",{dialog:this},function(t){var e=t.data.dialog;e.draggableData.isMouseDown&&e.getModalDialog().offset({top:t.clientY-e.draggableData.mouseOffset.top,left:t.clientX-e.draggableData.mouseOffset.left})})),this},realize:function(){return this.initModalStuff(),this.getModal().addClass(o.NAMESPACE).addClass(this.getCssClass()),this.updateSize(),this.getDescription()&&this.getModal().attr("aria-describedby",this.getDescription()),this.getModalFooter().append(this.createFooterContent()),this.getModalHeader().append(this.createHeaderContent()),this.getModalBody().append(this.createBodyContent()),this.getModal().data("bs.modal",new n(this.getModal(),{backdrop:"static",keyboard:!1,show:!1})),this.makeModalDraggable(),this.handleModalEvents(),this.setRealized(!0),this.updateButtons(),this.updateType(),this.updateTitle(),this.updateMessage(),this.updateClosable(),this.updateAnimate(),this.updateSize(),this.updateTabindex(),this},open:function(){return!this.isRealized()&&this.realize(),this.getModal().modal("show"),this},close:function(){return!this.isRealized()&&this.realize(),this.getModal().modal("hide"),this}},o.prototype=t.extend(o.prototype,o.METHODS_TO_OVERRIDE[n.getModalVersion()]),o.newGuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=16*Math.random()|0;return("x"===t?e:3&e|8).toString(16)})},o.show=function(t){return new o(t).open()},o.alert=function(){var e={},n={type:o.TYPE_PRIMARY,title:null,message:null,closable:!1,draggable:!1,buttonLabel:o.DEFAULT_TEXTS.OK,buttonHotkey:null,callback:null};e="object"==typeof arguments[0]&&arguments[0].constructor==={}.constructor?t.extend(!0,n,arguments[0]):t.extend(!0,n,{message:arguments[0],callback:void 0!==arguments[1]?arguments[1]:null});var i=new o(e);return i.setData("callback",e.callback),i.addButton({label:e.buttonLabel,hotkey:e.buttonHotkey,action:function(t){return("function"!=typeof t.getData("callback")||!1!==t.getData("callback").call(this,!0))&&(t.setData("btnClicked",!0),t.close())}}),"function"==typeof i.options.onhide?i.onHide(function(t){var e=!0;return!t.getData("btnClicked")&&t.isClosable()&&"function"==typeof t.getData("callback")&&(e=t.getData("callback")(!1)),!1!==e&&(e=this.onhide(t))}.bind({onhide:i.options.onhide})):i.onHide(function(t){var e=!0;return!t.getData("btnClicked")&&t.isClosable()&&"function"==typeof t.getData("callback")&&(e=t.getData("callback")(!1)),e}),i.open()},o.confirm=function(){var e={},n={type:o.TYPE_PRIMARY,title:null,message:null,closable:!1,draggable:!1,btnCancelLabel:o.DEFAULT_TEXTS.CANCEL,btnCancelClass:null,btnCancelHotkey:null,btnOKLabel:o.DEFAULT_TEXTS.OK,btnOKClass:null,btnOKHotkey:null,btnsOrder:o.defaultOptions.btnsOrder,callback:null};null===(e="object"==typeof arguments[0]&&arguments[0].constructor==={}.constructor?t.extend(!0,n,arguments[0]):t.extend(!0,n,{message:arguments[0],callback:void 0!==arguments[1]?arguments[1]:null})).btnOKClass&&(e.btnOKClass=["btn",e.type.split("-")[1]].join("-"));var i=new o(e);i.setData("callback",e.callback);var s=[{label:e.btnCancelLabel,cssClass:e.btnCancelClass,hotkey:e.btnCancelHotkey,action:function(t){return("function"!=typeof t.getData("callback")||!1!==t.getData("callback").call(this,!1))&&t.close()}},{label:e.btnOKLabel,cssClass:e.btnOKClass,hotkey:e.btnOKHotkey,action:function(t){return("function"!=typeof t.getData("callback")||!1!==t.getData("callback").call(this,!0))&&t.close()}}];return e.btnsOrder===o.BUTTONS_ORDER_OK_CANCEL&&s.reverse(),i.addButtons(s),i.open()},o.warning=function(t,e){return new o({type:o.TYPE_WARNING,message:t}).open()},o.danger=function(t,e){return new o({type:o.TYPE_DANGER,message:t}).open()},o.success=function(t,e){return new o({type:o.TYPE_SUCCESS,message:t}).open()},o});
--------------------------------------------------------------------------------
/examples/images/pig.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nakupanda/bootstrap3-dialog/a491a98c97921114883ad44e5715fe28396dbaea/examples/images/pig.ico
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | BootstrapDialog examples
12 |
17 |
18 |
19 |
20 |
Make use of Bootstrap's modal more monkey-friendly.
21 |
22 |
23 | Monkeys love the Modal Dialog from Bootstrap , but they're getting angry because they have to write this stuff:
24 |
25 |
<div class="modal fade"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <p>One fine body…</p> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-primary">Save changes</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal -->
26 |
27 |
28 | What they want is more like this:
29 |
30 |
31 | BootstrapDialog.alert('I want banana!');
32 |
33 |
34 |
35 | Like it? See Available Options or try more Examples below.
36 |
37 |
38 |
39 |
40 |
Examples
41 |
42 |
43 |
Simplest
44 |
Provide only the message to show, and keep all other things default.
45 |
46 |
51 |
52 |
53 |
Dialog Title
54 |
55 |
61 |
62 |
63 |
64 |
Manipulating Dialog Title
65 |
66 |
83 |
84 |
85 |
Manipulating Dialog Message
86 |
87 |
104 |
105 |
106 |
107 |
Loading remote page (1)
108 |
109 | There are some workarounds for loading remote page into BootstrapDialog as message, one of those workarounds is as below.
110 | Check out the remote.html .
111 |
112 |
113 |
118 |
119 |
120 |
Loading remote page (2)
121 |
122 | Another solution of loading remote page into BootstrapDialog.
123 | This one is more flexible and customizable, but it's also a bit more complicated to use.
124 |
125 |
126 |
140 |
141 |
142 |
Buttons
143 |
144 |
174 |
175 |
176 |
Manipulating Buttons
177 |
178 | Buttons that created by BootstrapDialog have some extra functions available:
179 | $button.toggleEnable(true|false);
180 | $button.enable(); // Equals to $button.toggleEnable(true);
181 | $button.disable(); // Equals to $button.toggleEnable(false);
182 | $button.toggleSpin(true|false);
183 | $button.spin(); // Equals to $button.toggleSpin(true);
184 | $button.stopSpin(); // Equals to $button.toggleSpin(false);
185 |
186 |
187 |
213 |
214 |
215 |
216 |
Button Hotkey
217 |
218 | Try to press the keys that have been associated with buttons below.
219 | The last button is disabled so nothing is going to happen when pressing its hotkey.
220 | Please note that if there are some components that require keyboard operations in your dialog, conflicts may occur, you can try next example.
221 |
222 |
223 |
252 |
253 |
254 |
Keys Conflicts
255 |
Try to avoid doing similar in your code.
256 |
257 |
271 |
272 |
273 |
274 |
Opening multiple dialogs
275 |
A good looking stacked dialogs. Please also note the second and the third dialog are draggable.
276 |
277 |
302 |
303 |
304 |
Creating dialog instances
305 |
BootstrapDialog.show(...) is just a shortcut method, if you need dialog instances, use 'new'.
306 |
307 |
329 |
330 |
In fact BootstrapDialog.show(...) will also return the created dialog instance.
331 |
332 |
338 |
339 |
340 |
Open / Close multiple dialogs
341 |
This example demonstrates opening and closing a batch of dialogs at one time. Dialog that created by BootstrapDialog will be in a container BootstrapDialog.dialogs before it's closed and destroyed, iterate BootstrapDialog.dialogs to find all dialogs that havn't been destroyed.
342 |
343 |
368 |
369 |
370 |
Button with identifier
371 |
372 |
387 |
388 |
389 |
Message types
390 |
391 |
410 |
411 |
412 |
413 |
Changing dialog type
414 |
415 |
440 |
441 |
442 |
Larger dialog
443 |
444 | By default, the dialog size is 'size-normal' or BootstrapDialog.SIZE_NORMAL, but you can have a larger dialog by setting option 'size' to 'size-large' or BootstrapDialog.SIZE_LARGE.
445 |
446 |
447 |
471 |
472 |
473 |
474 |
More dialog sizes
475 |
476 | Please note that specifying BootstrapDialog.SIZE_WIDE is equal to using css class 'modal-lg' on Bootstrap Modal.
477 |
478 |
479 |
510 |
511 |
512 |
Rich message
513 |
BootstrapDialog supports displaying rich content, so you can even use a video clip as your message in the dialog.
514 |
515 |
536 |
537 |
538 |
Dialog closable / unclosable
539 |
540 | If option 'closable' is set to false, the default closing behaviors will be disabled, but you can still close the dialog by using dialog.close().
541 |
542 |
543 |
567 |
568 |
569 |
570 |
More controls on closing a dialog.
571 |
572 | By default, when option 'closable' is set to true, dialog can be closed by these ways: clicking outside the dialog, pressing ESC key, clicking the close icon on the right of dialog header.
573 | If you want your dialog closes only when the close icon in dialog header was clicked, try setting both of the options 'closeByBackdrop' and 'closeByKeyboard' to false.
574 |
575 |
576 |
591 |
592 |
593 |
594 |
Disabling Animation
595 |
596 | Setting option 'animate' to false to disable animation for the opening dialog.
597 | If you want to disable animation globally, try to do this:
598 | BootstrapDialog.configDefaultOptions({
599 | animate: false
600 | });
601 |
602 |
603 |
615 |
616 |
617 |
Auto spinning icon
618 |
619 | Lazy guys must love this.
620 |
621 |
622 |
646 |
647 |
648 |
649 |
Dialog Draggable
650 |
651 | When option 'draggable' is set to true , your dialog can be moved by dragging on its header.
652 | If you would like to change the cursor shape of hovering on dialog header, you can try the following css lines:
653 |
654 | .bootstrap-dialog .modal-header.bootstrap-dialog-draggable {
655 | cursor: move;
656 | }
657 |
658 |
659 |
660 |
667 |
668 |
669 |
Manipulating your dialog
670 |
671 |
692 |
693 |
694 |
Adding additional css classes to your dialog
695 |
This is useful for applying effects to specific dialogs.
696 | For example if you would like to give your 'login-dialog' a smaller size, you can do this way:
697 |
698 |
705 |
706 |
707 |
721 |
722 |
723 |
Adding a description to your dialog (for accessibility)
724 |
This adds an 'aria-describedby' attribute to your dialog, which provides a description of the dialog for screen readers.
725 |
726 |
733 |
734 |
735 |
Data binding
736 |
737 |
759 |
760 |
761 |
Dialog events
762 |
763 | Please note that if you're going to use setters to configure event handlers, use dialog.onShow(function) and dialog.onHide(function).
764 |
765 |
766 |
783 |
784 |
785 |
786 |
Stop closing your dialog.
787 |
788 | Option 'onhide' gives you an opportunity to stop closing the dialog according to some conditions, making your 'onhide' callback returns false to stop closing the dialog.
789 | In the following example, the dialog closes only when your most favorite fruit is 'banana ' (Case insensitive).
790 |
791 |
792 |
810 |
811 |
812 |
More shortcut methods
813 |
814 |
Alert
815 |
816 |
819 |
820 |
821 |
Alert with callback
822 |
823 |
828 |
829 |
830 |
831 |
Customizing dialog type, title, and more.
832 |
All options shown below are optional.
833 |
834 |
848 |
849 |
850 |
Confirm
851 |
852 |
855 |
856 |
857 |
Confirm with callback
858 |
859 |
868 |
869 |
870 |
871 |
Just like what we have done in alert, we can control confirm dialog more.
872 |
873 |
893 |
894 |
895 |
896 |
I18N
897 |
To provide local messages for you needed, reset those messages below before using BootstrapDialog.
898 |
899 |
910 |
911 |
912 |
913 |
914 |
Available options
915 |
916 |
917 | Please note that all options described below are optional , but you will have a weird dialog if you don't even give it a message to display.
918 |
919 | Most options can be set via init options or property setters.
920 |
921 |
922 |
923 |
924 |
925 | Option
926 |
927 |
928 | Possible values
929 |
930 |
931 | Description
932 |
933 |
934 |
935 |
936 |
937 | type
938 |
939 | BootstrapDialog.TYPE_DEFAULT or 'type-default'
940 | BootstrapDialog.TYPE_INFO or 'type-info'
941 | BootstrapDialog.TYPE_PRIMARY or 'type-primary' (default)
942 | BootstrapDialog.TYPE_SUCCESS or 'type-success'
943 | BootstrapDialog.TYPE_WARNING or 'type-warning'
944 | BootstrapDialog.TYPE_DANGER or 'type-danger'
945 |
946 |
947 | Give your dialog a specific look, color scheme can be seen on Bootstrap's Button .
948 |
949 |
950 |
951 | size
952 |
953 | BootstrapDialog.SIZE_NORMAL or 'size-normal' (default)
954 | BootstrapDialog.SIZE_WIDE or 'size-wide'
955 | BootstrapDialog.SIZE_LARGE or 'size-large'
956 |
957 |
958 | -
959 |
960 |
961 |
962 | cssClass
963 |
964 | -
965 |
966 |
967 | Additional css classes that will be added to your dialog.
968 |
969 |
970 |
971 | title
972 |
973 | String or Object(html)
974 |
975 |
976 | -
977 |
978 |
979 |
980 | message
981 |
982 | String or Object(html)
983 |
984 |
985 | -
986 |
987 |
988 |
989 | buttons
990 |
991 | array
992 |
993 |
994 | Examples:
995 |
996 | BootstrapDialog.show({
997 | title: 'Say-hello dialog',
998 | message: 'Hello world!',
999 | buttons: [{
1000 | id: 'btn-ok',
1001 | icon: 'glyphicon glyphicon-check',
1002 | label: 'OK',
1003 | cssClass: 'btn-primary',
1004 | data: {
1005 | js: 'btn-confirm',
1006 | 'user-id': '3'
1007 | },
1008 | autospin: false,
1009 | action: function(dialogRef){
1010 | dialogRef.close();
1011 | }
1012 | }]
1013 | });
1014 |
1015 | id : optional, if id is set, you can use dialogInstance.getButton(id) to get the button later.
1016 | icon : optional, if set, the specified icon will be added to the button.
1017 | cssClass : optional, additional css class to be added to the button.
1018 | data : optional, object containing data attributes to be added to the button.
1019 | autospin : optional, if it's true, after clicked the button a spinning icon appears.
1020 | action : optional, if provided, the callback will be invoked after the button is clicked, and the dialog instance will be passed to the callback function.
1021 |
1022 |
1023 |
1024 | closable
1025 |
1026 | true | false
1027 |
1028 |
1029 | When set to true , you can close the dialog by:
1030 |
1031 | Clicking the close icon in dialog header.
1032 | Clicking outside the dialog.
1033 | ESC key.
1034 |
1035 |
1036 |
1037 |
1038 | spinicon
1039 |
1040 | Icon class name, for example 'glyphicon glyphicon-check'.
1041 | Default value is 'glyphicon glyphicon-asterisk'.
1042 |
1043 |
1044 | Specify what icon to be used as the spinning icon when button's 'autospin' is set to true.
1045 |
1046 |
1047 |
1048 | data
1049 |
1050 | Key-value object. For example {'id' : '100'}
1051 |
1052 |
1053 | Data to be bound to the dialog.
1054 |
1055 |
1056 |
1057 | onshow
1058 |
1059 | function
1060 |
1061 |
1062 | If provided, it will be invoked when the dialog is popping up.
1063 |
1064 |
1065 |
1066 | onshown
1067 |
1068 | function
1069 |
1070 |
1071 | If provided, it will be invoked when the dialog is popped up.
1072 |
1073 |
1074 |
1075 | onhide
1076 |
1077 | function
1078 |
1079 |
1080 | If provided, it will be invoked when the dialog is popping down.
1081 |
1082 |
1083 |
1084 | onhidden
1085 |
1086 | function
1087 |
1088 |
1089 | If provided, it will be invoked when the dialog is popped down.
1090 |
1091 |
1092 |
1093 | autodestroy
1094 |
1095 | true (default) | false
1096 |
1097 |
1098 | When it's true, all modal stuff will be removed from the DOM tree after the dialog is popped down, set it to false if you need your dialog (same instance) pups up and down again and again.
1099 |
1100 |
1101 |
1102 | description
1103 |
1104 | String
1105 |
1106 |
1107 | If provided, 'aria-describedby' attribute will be added to the dialog with the description string as its value. This can improve accessibility, as the description can be read by screen readers.
1108 |
1109 |
1110 |
1111 | nl2br
1112 |
1113 | true | false
1114 |
1115 |
1116 | Automatically convert line breaking character to <br /> if it's set to true, everything keeps original if it's false.
1117 |
1118 |
1119 |
1120 |
1121 |
1122 |
1123 |
1124 |
1125 |
Available methods
1126 |
1127 |
1128 |
1129 |
1130 |
1131 | Method
1132 |
1133 |
1134 | Description
1135 |
1136 |
1137 |
1138 |
1139 |
1140 | open()
1141 | Open the dialog. Usage: dialogInstance.open()
1142 |
1143 |
1144 | close()
1145 | Close the dialog. Usage: dialogInstance.close()
1146 |
1147 |
1148 | getModal()
1149 | Return the raw modal, equivalent to $('<div class='modal fade'...></div>')
1150 |
1151 |
1152 | getModalDialog()
1153 | Return the raw modal dialog.
1154 |
1155 |
1156 | getModalContent()
1157 | Return the raw modal content.
1158 |
1159 |
1160 | getModalHeader()
1161 | Return the raw modal header.
1162 |
1163 |
1164 | getModalBody()
1165 | Return the raw modal body.
1166 |
1167 |
1168 | getModalFooter()
1169 | Return the raw modal footer.
1170 |
1171 |
1172 | getData(key)
1173 | Get data entry according to the given key, returns null if no data entry found.
1174 |
1175 |
1176 | setData(key, value)
1177 | Bind data entry to dialog instance, value can be any types that javascript supports.
1178 |
1179 |
1180 | enableButtons(boolean)
1181 | Disable all buttons in dialog footer when it's false, enable all when it's true.
1182 |
1183 |
1184 | setClosable(boolean)
1185 | When set to true (default), dialog can be closed by clicking close icon in dialog header, or by clicking outside the dialog, or, ESC key is pressed.
1186 |
1187 |
1188 | realize()
1189 | Calling dialog.open() will automatically get this method called first, but if you want to do something on your dialog before it's shown, you can manually call dialog.realize() before calling dialog.open().
1190 |
1191 |
1192 |
1193 |
1194 |
1195 |
Go to the project. | Contact me if you can help to improve this example page.
1196 |
1197 |
1198 |
1221 |
1222 |
1223 |
--------------------------------------------------------------------------------
/examples/play/append-to-div.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Append modal to div
11 |
12 |
13 |
14 |
15 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/examples/play/button-event.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Button Event
11 |
12 |
13 |
14 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/examples/play/custom-dialog-id.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Dialog ID
11 |
12 |
13 |
14 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/examples/play/only-one-dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Only one dialog
12 |
13 |
24 |
25 |
26 |
29 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/examples/play/reopen-dialog.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Reopen Dialog
11 |
12 |
13 |
14 | Open your dialog
15 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/examples/play/spinning-icon.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Spinning Icon
12 |
13 |
14 |
15 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/examples/play/tabindex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Tabindex
12 |
13 |
14 |
15 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/examples/remote.html:
--------------------------------------------------------------------------------
1 | Hello, this is a message from remote.html!
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | // Gulpfile.js
2 |
3 | "use strict";
4 |
5 | var gulp = require("gulp"),
6 | eslint = require("gulp-eslint"),
7 | less = require("gulp-less"),
8 | minifyCSS = require("gulp-minify-css"),
9 | path = require("path"),
10 | notify = require("gulp-notify"),
11 | clean = require("gulp-clean"),
12 | rename = require("gulp-rename"),
13 | concat = require("gulp-concat"),
14 | uglify = require("gulp-uglify");
15 |
16 | var less_src = [
17 | "node_modules/bootstrap/less/variables.less",
18 | "node_modules/bootstrap/less/mixins/*.less",
19 | "src/less/bootstrap-dialog.less"
20 | ];
21 |
22 | gulp.task("less", function() {
23 | gulp.src(less_src)
24 | .pipe(concat("bootstrap-dialog.less"))
25 | .pipe(gulp.dest("dist/less"))
26 | .pipe(less())
27 | .pipe(gulp.dest("dist/css"))
28 | .pipe(gulp.dest("src/css"))
29 | .pipe(rename("bootstrap-dialog.min.css"))
30 | .pipe(minifyCSS())
31 | .pipe(gulp.dest("dist/css"));
32 | });
33 |
34 | gulp.task("lint", function() {
35 | gulp.src(["src/js/bootstrap-dialog.js"])
36 | .pipe(eslint())
37 | .pipe(eslint.format());
38 | });
39 |
40 | gulp.task("dist", ["clean", "less"], function() {
41 | gulp.src(["src/js/bootstrap-dialog.js"])
42 | .pipe(gulp.dest("dist/js"))
43 | .pipe(rename("bootstrap-dialog.min.js"))
44 | .pipe(uglify())
45 | .pipe(gulp.dest("dist/js"))
46 | .pipe(notify({
47 | message: "Build task completed."
48 | }));
49 | });
50 |
51 | gulp.task("clean", function() {
52 | return gulp.src(["dist/"], {
53 | read: false
54 | })
55 | .pipe(clean());
56 | });
57 |
58 | gulp.task("default", ["clean"], function() {
59 | gulp.start("dist");
60 | });
61 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bootstrap3-dialog",
3 | "version": "1.35.4",
4 | "description": "Make use of Bootstrap Modal more monkey-friendly.",
5 | "directories": {
6 | "example": "examples"
7 | },
8 | "main": "dist/js/bootstrap-dialog.js",
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/nakupanda/bootstrap3-dialog.git"
15 | },
16 | "keywords": [
17 | "bootstrap",
18 | "dialog"
19 | ],
20 | "author": "nakupanda",
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/nakupanda/bootstrap3-dialog/issues"
24 | },
25 | "homepage": "http://nakupanda.github.io/bootstrap3-dialog",
26 | "devDependencies": {
27 | "bootstrap": ">=3.1.0",
28 | "eslint": ">=0.6.2",
29 | "gulp": ">=3.8.1",
30 | "gulp-clean": ">=0.3.0",
31 | "gulp-concat": "^2.5.2",
32 | "gulp-eslint": ">=0.1.7",
33 | "gulp-less": ">=1.2.3",
34 | "gulp-minify-css": "^0.3.4",
35 | "gulp-notify": ">=1.3.1",
36 | "gulp-rename": ">=1.2.0",
37 | "gulp-streamify": "0.0.5",
38 | "gulp-uglify": ">=0.3.0",
39 | "vinyl-source-stream": "^0.1.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/css/bootstrap-dialog.css:
--------------------------------------------------------------------------------
1 | .bootstrap-dialog {
2 | /* dialog types */
3 | /**
4 | * Icon animation
5 | * Copied from font-awesome: http://fontawesome.io/
6 | **/
7 | /** End of icon animation **/
8 | }
9 | .bootstrap-dialog .modal-header {
10 | border-top-left-radius: 4px;
11 | border-top-right-radius: 4px;
12 | }
13 | .bootstrap-dialog .bootstrap-dialog-title {
14 | color: #fff;
15 | display: inline-block;
16 | font-size: 16px;
17 | }
18 | .bootstrap-dialog .bootstrap-dialog-message {
19 | font-size: 14px;
20 | }
21 | .bootstrap-dialog .bootstrap-dialog-button-icon {
22 | margin-right: 3px;
23 | }
24 | .bootstrap-dialog .bootstrap-dialog-close-button {
25 | font-size: 20px;
26 | float: right;
27 | opacity: 0.9;
28 | filter: alpha(opacity=90);
29 | }
30 | .bootstrap-dialog .bootstrap-dialog-close-button:hover {
31 | cursor: pointer;
32 | opacity: 1;
33 | filter: alpha(opacity=100);
34 | }
35 | .bootstrap-dialog.type-default .modal-header {
36 | background-color: #ffffff;
37 | }
38 | .bootstrap-dialog.type-default .bootstrap-dialog-title {
39 | color: #333;
40 | }
41 | .bootstrap-dialog.type-info .modal-header {
42 | background-color: #5bc0de;
43 | }
44 | .bootstrap-dialog.type-primary .modal-header {
45 | background-color: #337ab7;
46 | }
47 | .bootstrap-dialog.type-success .modal-header {
48 | background-color: #5cb85c;
49 | }
50 | .bootstrap-dialog.type-warning .modal-header {
51 | background-color: #f0ad4e;
52 | }
53 | .bootstrap-dialog.type-danger .modal-header {
54 | background-color: #d9534f;
55 | }
56 | .bootstrap-dialog.size-large .bootstrap-dialog-title {
57 | font-size: 24px;
58 | }
59 | .bootstrap-dialog.size-large .bootstrap-dialog-close-button {
60 | font-size: 30px;
61 | }
62 | .bootstrap-dialog.size-large .bootstrap-dialog-message {
63 | font-size: 18px;
64 | }
65 | .bootstrap-dialog .icon-spin {
66 | display: inline-block;
67 | -moz-animation: spin 2s infinite linear;
68 | -o-animation: spin 2s infinite linear;
69 | -webkit-animation: spin 2s infinite linear;
70 | animation: spin 2s infinite linear;
71 | }
72 | @-moz-keyframes spin {
73 | 0% {
74 | -moz-transform: rotate(0deg);
75 | }
76 | 100% {
77 | -moz-transform: rotate(359deg);
78 | }
79 | }
80 | @-webkit-keyframes spin {
81 | 0% {
82 | -webkit-transform: rotate(0deg);
83 | }
84 | 100% {
85 | -webkit-transform: rotate(359deg);
86 | }
87 | }
88 | @-o-keyframes spin {
89 | 0% {
90 | -o-transform: rotate(0deg);
91 | }
92 | 100% {
93 | -o-transform: rotate(359deg);
94 | }
95 | }
96 | @-ms-keyframes spin {
97 | 0% {
98 | -ms-transform: rotate(0deg);
99 | }
100 | 100% {
101 | -ms-transform: rotate(359deg);
102 | }
103 | }
104 | @keyframes spin {
105 | 0% {
106 | transform: rotate(0deg);
107 | }
108 | 100% {
109 | transform: rotate(359deg);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/js/bootstrap-dialog.js:
--------------------------------------------------------------------------------
1 | /* global define */
2 |
3 | /* ================================================
4 | * Make use of Bootstrap's modal more monkey-friendly.
5 | *
6 | * For Bootstrap 3.
7 | *
8 | * javanoob@hotmail.com
9 | *
10 | * https://github.com/nakupanda/bootstrap3-dialog
11 | *
12 | * Licensed under The MIT License.
13 | * ================================================ */
14 | (function (root, factory) {
15 |
16 | "use strict";
17 |
18 | // CommonJS module is defined
19 | if (typeof module !== 'undefined' && module.exports) {
20 | module.exports = factory(require('jquery'), require('bootstrap'));
21 | }
22 | // AMD module is defined
23 | else if (typeof define === "function" && define.amd) {
24 | define("bootstrap-dialog", ["jquery", "bootstrap"], function ($) {
25 | return factory($);
26 | });
27 | } else {
28 | // planted over the root!
29 | root.BootstrapDialog = factory(root.jQuery);
30 | }
31 |
32 | }(this, function ($) {
33 |
34 | "use strict";
35 |
36 | /* ================================================
37 | * Definition of BootstrapDialogModal.
38 | * Extend Bootstrap Modal and override some functions.
39 | * BootstrapDialogModal === Modified Modal.
40 | * ================================================ */
41 | var Modal = $.fn.modal.Constructor;
42 | var BootstrapDialogModal = function (element, options) {
43 | Modal.call(this, element, options);
44 | };
45 | BootstrapDialogModal.getModalVersion = function () {
46 | var version = null;
47 | if (typeof $.fn.modal.Constructor.VERSION === 'undefined') {
48 | version = 'v3.1';
49 | } else if (/3\.2\.\d+/.test($.fn.modal.Constructor.VERSION)) {
50 | version = 'v3.2';
51 | } else if (/3\.3\.[1,2]/.test($.fn.modal.Constructor.VERSION)) {
52 | version = 'v3.3'; // v3.3.1, v3.3.2
53 | } else {
54 | version = 'v3.3.4';
55 | }
56 |
57 | return version;
58 | };
59 | BootstrapDialogModal.ORIGINAL_BODY_PADDING = parseInt(($('body').css('padding-right') || 0), 10);
60 | BootstrapDialogModal.METHODS_TO_OVERRIDE = {};
61 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.1'] = {};
62 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.2'] = {
63 | hide: function (e) {
64 | if (e) {
65 | e.preventDefault();
66 | }
67 | e = $.Event('hide.bs.modal');
68 |
69 | this.$element.trigger(e);
70 |
71 | if (!this.isShown || e.isDefaultPrevented()) {
72 | return;
73 | }
74 |
75 | this.isShown = false;
76 |
77 | // Remove css class 'modal-open' when the last opened dialog is closing.
78 | var openedDialogs = this.getGlobalOpenedDialogs();
79 | if (openedDialogs.length === 0) {
80 | this.$body.removeClass('modal-open');
81 | }
82 |
83 | this.resetScrollbar();
84 | this.escape();
85 |
86 | $(document).off('focusin.bs.modal');
87 |
88 | this.$element
89 | .removeClass('in')
90 | .attr('aria-hidden', true)
91 | .off('click.dismiss.bs.modal');
92 |
93 | $.support.transition && this.$element.hasClass('fade') ?
94 | this.$element
95 | .one('bsTransitionEnd', $.proxy(this.hideModal, this))
96 | .emulateTransitionEnd(300) :
97 | this.hideModal();
98 | }
99 | };
100 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3'] = {
101 | /**
102 | * Overrided.
103 | *
104 | * @returns {undefined}
105 | */
106 | setScrollbar: function () {
107 | var bodyPad = BootstrapDialogModal.ORIGINAL_BODY_PADDING;
108 | if (this.bodyIsOverflowing) {
109 | this.$body.css('padding-right', bodyPad + this.scrollbarWidth);
110 | }
111 | },
112 | /**
113 | * Overrided.
114 | *
115 | * @returns {undefined}
116 | */
117 | resetScrollbar: function () {
118 | var openedDialogs = this.getGlobalOpenedDialogs();
119 | if (openedDialogs.length === 0) {
120 | this.$body.css('padding-right', BootstrapDialogModal.ORIGINAL_BODY_PADDING);
121 | }
122 | },
123 | /**
124 | * Overrided.
125 | *
126 | * @returns {undefined}
127 | */
128 | hideModal: function () {
129 | this.$element.hide();
130 | this.backdrop($.proxy(function () {
131 | var openedDialogs = this.getGlobalOpenedDialogs();
132 | if (openedDialogs.length === 0) {
133 | this.$body.removeClass('modal-open');
134 | }
135 | this.resetAdjustments();
136 | this.resetScrollbar();
137 | this.$element.trigger('hidden.bs.modal');
138 | }, this));
139 | }
140 | };
141 | BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3.4'] = $.extend({}, BootstrapDialogModal.METHODS_TO_OVERRIDE['v3.3']);
142 | BootstrapDialogModal.prototype = {
143 | constructor: BootstrapDialogModal,
144 | /**
145 | * New function, to get the dialogs that opened by BootstrapDialog.
146 | *
147 | * @returns {undefined}
148 | */
149 | getGlobalOpenedDialogs: function () {
150 | var openedDialogs = [];
151 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
152 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
153 | openedDialogs.push(dialogInstance);
154 | }
155 | });
156 |
157 | return openedDialogs;
158 | }
159 | };
160 |
161 | // Add compatible methods.
162 | BootstrapDialogModal.prototype = $.extend(BootstrapDialogModal.prototype, Modal.prototype, BootstrapDialogModal.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
163 |
164 | /* ================================================
165 | * Definition of BootstrapDialog.
166 | * ================================================ */
167 | var BootstrapDialog = function (options) {
168 | this.defaultOptions = $.extend(true, {
169 | id: BootstrapDialog.newGuid(),
170 | buttons: [],
171 | data: {},
172 | onshow: null,
173 | onshown: null,
174 | onhide: null,
175 | onhidden: null
176 | }, BootstrapDialog.defaultOptions);
177 | this.indexedButtons = {};
178 | this.registeredButtonHotkeys = {};
179 | this.draggableData = {
180 | isMouseDown: false,
181 | mouseOffset: {}
182 | };
183 | this.realized = false;
184 | this.opened = false;
185 | this.initOptions(options);
186 | this.holdThisInstance();
187 | };
188 |
189 | BootstrapDialog.BootstrapDialogModal = BootstrapDialogModal;
190 |
191 | /**
192 | * Some constants.
193 | */
194 | BootstrapDialog.NAMESPACE = 'bootstrap-dialog';
195 | BootstrapDialog.TYPE_DEFAULT = 'type-default';
196 | BootstrapDialog.TYPE_INFO = 'type-info';
197 | BootstrapDialog.TYPE_PRIMARY = 'type-primary';
198 | BootstrapDialog.TYPE_SUCCESS = 'type-success';
199 | BootstrapDialog.TYPE_WARNING = 'type-warning';
200 | BootstrapDialog.TYPE_DANGER = 'type-danger';
201 | BootstrapDialog.DEFAULT_TEXTS = {};
202 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_DEFAULT] = 'Information';
203 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_INFO] = 'Information';
204 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_PRIMARY] = 'Information';
205 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_SUCCESS] = 'Success';
206 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_WARNING] = 'Warning';
207 | BootstrapDialog.DEFAULT_TEXTS[BootstrapDialog.TYPE_DANGER] = 'Danger';
208 | BootstrapDialog.DEFAULT_TEXTS['OK'] = 'OK';
209 | BootstrapDialog.DEFAULT_TEXTS['CANCEL'] = 'Cancel';
210 | BootstrapDialog.DEFAULT_TEXTS['CONFIRM'] = 'Confirmation';
211 | BootstrapDialog.SIZE_NORMAL = 'size-normal';
212 | BootstrapDialog.SIZE_SMALL = 'size-small';
213 | BootstrapDialog.SIZE_WIDE = 'size-wide'; // size-wide is equal to modal-lg
214 | BootstrapDialog.SIZE_LARGE = 'size-large';
215 | BootstrapDialog.BUTTON_SIZES = {};
216 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_NORMAL] = '';
217 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_SMALL] = '';
218 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_WIDE] = '';
219 | BootstrapDialog.BUTTON_SIZES[BootstrapDialog.SIZE_LARGE] = 'btn-lg';
220 | BootstrapDialog.ICON_SPINNER = 'glyphicon glyphicon-asterisk';
221 | BootstrapDialog.BUTTONS_ORDER_CANCEL_OK = 'btns-order-cancel-ok';
222 | BootstrapDialog.BUTTONS_ORDER_OK_CANCEL = 'btns-order-ok-cancel';
223 |
224 | /**
225 | * Default options.
226 | */
227 | BootstrapDialog.defaultOptions = {
228 | type: BootstrapDialog.TYPE_PRIMARY,
229 | size: BootstrapDialog.SIZE_NORMAL,
230 | cssClass: '',
231 | title: null,
232 | message: null,
233 | nl2br: true,
234 | closable: true,
235 | closeByBackdrop: true,
236 | closeByKeyboard: true,
237 | closeIcon: '×',
238 | spinicon: BootstrapDialog.ICON_SPINNER,
239 | autodestroy: true,
240 | draggable: false,
241 | animate: true,
242 | description: '',
243 | tabindex: -1,
244 | btnsOrder: BootstrapDialog.BUTTONS_ORDER_CANCEL_OK
245 | };
246 |
247 | /**
248 | * Config default options.
249 | */
250 | BootstrapDialog.configDefaultOptions = function (options) {
251 | BootstrapDialog.defaultOptions = $.extend(true, BootstrapDialog.defaultOptions, options);
252 | };
253 |
254 | /**
255 | * Open / Close all created dialogs all at once.
256 | */
257 | BootstrapDialog.dialogs = {};
258 | BootstrapDialog.openAll = function () {
259 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
260 | dialogInstance.open();
261 | });
262 | };
263 | BootstrapDialog.closeAll = function () {
264 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
265 | dialogInstance.close();
266 | });
267 | };
268 |
269 | /**
270 | * Get dialog instance by given id.
271 | *
272 | * @returns dialog instance
273 | */
274 | BootstrapDialog.getDialog = function (id) {
275 | var dialog = null;
276 | if (typeof BootstrapDialog.dialogs[id] !== 'undefined') {
277 | dialog = BootstrapDialog.dialogs[id];
278 | }
279 |
280 | return dialog;
281 | };
282 |
283 | /**
284 | * Set a dialog.
285 | *
286 | * @returns the dialog that has just been set.
287 | */
288 | BootstrapDialog.setDialog = function (dialog) {
289 | BootstrapDialog.dialogs[dialog.getId()] = dialog;
290 |
291 | return dialog;
292 | };
293 |
294 | /**
295 | * Alias of BootstrapDialog.setDialog(dialog)
296 | *
297 | * @param {type} dialog
298 | * @returns {unresolved}
299 | */
300 | BootstrapDialog.addDialog = function (dialog) {
301 | return BootstrapDialog.setDialog(dialog);
302 | };
303 |
304 | /**
305 | * Move focus to next visible dialog.
306 | */
307 | BootstrapDialog.moveFocus = function () {
308 | var lastDialogInstance = null;
309 | $.each(BootstrapDialog.dialogs, function (id, dialogInstance) {
310 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
311 | lastDialogInstance = dialogInstance;
312 | }
313 | });
314 | if (lastDialogInstance !== null) {
315 | lastDialogInstance.getModal().focus();
316 | }
317 | };
318 |
319 | BootstrapDialog.METHODS_TO_OVERRIDE = {};
320 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.1'] = {
321 | handleModalBackdropEvent: function () {
322 | this.getModal().on('click', {dialog: this}, function (event) {
323 | event.target === this && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
324 | });
325 |
326 | return this;
327 | },
328 | /**
329 | * To make multiple opened dialogs look better.
330 | *
331 | * Will be removed in later version, after Bootstrap Modal >= 3.3.0, updating z-index is unnecessary.
332 | */
333 | updateZIndex: function () {
334 | if (this.isOpened()) {
335 | var zIndexBackdrop = 1040;
336 | var zIndexModal = 1050;
337 | var dialogCount = 0;
338 | $.each(BootstrapDialog.dialogs, function (dialogId, dialogInstance) {
339 | if (dialogInstance.isRealized() && dialogInstance.isOpened()) {
340 | dialogCount++;
341 | }
342 | });
343 | var $modal = this.getModal();
344 | var $backdrop = $modal.data('bs.modal').$backdrop;
345 | $modal.css('z-index', zIndexModal + (dialogCount - 1) * 20);
346 | $backdrop.css('z-index', zIndexBackdrop + (dialogCount - 1) * 20);
347 | }
348 |
349 | return this;
350 | },
351 | open: function () {
352 | !this.isRealized() && this.realize();
353 | this.getModal().modal('show');
354 | this.updateZIndex();
355 |
356 | return this;
357 | }
358 | };
359 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.2'] = {
360 | handleModalBackdropEvent: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['handleModalBackdropEvent'],
361 | updateZIndex: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['updateZIndex'],
362 | open: BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']['open']
363 | };
364 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.3'] = {};
365 | BootstrapDialog.METHODS_TO_OVERRIDE['v3.3.4'] = $.extend({}, BootstrapDialog.METHODS_TO_OVERRIDE['v3.1']);
366 | BootstrapDialog.prototype = {
367 | constructor: BootstrapDialog,
368 | initOptions: function (options) {
369 | this.options = $.extend(true, this.defaultOptions, options);
370 |
371 | return this;
372 | },
373 | holdThisInstance: function () {
374 | BootstrapDialog.addDialog(this);
375 |
376 | return this;
377 | },
378 | initModalStuff: function () {
379 | this.setModal(this.createModal())
380 | .setModalDialog(this.createModalDialog())
381 | .setModalContent(this.createModalContent())
382 | .setModalHeader(this.createModalHeader())
383 | .setModalBody(this.createModalBody())
384 | .setModalFooter(this.createModalFooter());
385 |
386 | this.getModal().append(this.getModalDialog());
387 | this.getModalDialog().append(this.getModalContent());
388 | this.getModalContent()
389 | .append(this.getModalHeader())
390 | .append(this.getModalBody())
391 | .append(this.getModalFooter());
392 |
393 | return this;
394 | },
395 | createModal: function () {
396 | var $modal = $('
');
397 | $modal.prop('id', this.getId());
398 | $modal.attr('aria-labelledby', this.getId() + '_title');
399 |
400 | return $modal;
401 | },
402 | getModal: function () {
403 | return this.$modal;
404 | },
405 | setModal: function ($modal) {
406 | this.$modal = $modal;
407 |
408 | return this;
409 | },
410 | createModalDialog: function () {
411 | return $('
');
412 | },
413 | getModalDialog: function () {
414 | return this.$modalDialog;
415 | },
416 | setModalDialog: function ($modalDialog) {
417 | this.$modalDialog = $modalDialog;
418 |
419 | return this;
420 | },
421 | createModalContent: function () {
422 | return $('
');
423 | },
424 | getModalContent: function () {
425 | return this.$modalContent;
426 | },
427 | setModalContent: function ($modalContent) {
428 | this.$modalContent = $modalContent;
429 |
430 | return this;
431 | },
432 | createModalHeader: function () {
433 | return $('');
434 | },
435 | getModalHeader: function () {
436 | return this.$modalHeader;
437 | },
438 | setModalHeader: function ($modalHeader) {
439 | this.$modalHeader = $modalHeader;
440 |
441 | return this;
442 | },
443 | createModalBody: function () {
444 | return $('
');
445 | },
446 | getModalBody: function () {
447 | return this.$modalBody;
448 | },
449 | setModalBody: function ($modalBody) {
450 | this.$modalBody = $modalBody;
451 |
452 | return this;
453 | },
454 | createModalFooter: function () {
455 | return $('');
456 | },
457 | getModalFooter: function () {
458 | return this.$modalFooter;
459 | },
460 | setModalFooter: function ($modalFooter) {
461 | this.$modalFooter = $modalFooter;
462 |
463 | return this;
464 | },
465 | createDynamicContent: function (rawContent) {
466 | var content = null;
467 | if (typeof rawContent === 'function') {
468 | content = rawContent.call(rawContent, this);
469 | } else {
470 | content = rawContent;
471 | }
472 | if (typeof content === 'string') {
473 | content = this.formatStringContent(content);
474 | }
475 |
476 | return content;
477 | },
478 | formatStringContent: function (content) {
479 | if (this.options.nl2br) {
480 | return content.replace(/\r\n/g, ' ').replace(/[\r\n]/g, ' ');
481 | }
482 |
483 | return content;
484 | },
485 | setData: function (key, value) {
486 | this.options.data[key] = value;
487 |
488 | return this;
489 | },
490 | getData: function (key) {
491 | return this.options.data[key];
492 | },
493 | setId: function (id) {
494 | this.options.id = id;
495 |
496 | return this;
497 | },
498 | getId: function () {
499 | return this.options.id;
500 | },
501 | getType: function () {
502 | return this.options.type;
503 | },
504 | setType: function (type) {
505 | this.options.type = type;
506 | this.updateType();
507 |
508 | return this;
509 | },
510 | updateType: function () {
511 | if (this.isRealized()) {
512 | var types = [BootstrapDialog.TYPE_DEFAULT,
513 | BootstrapDialog.TYPE_INFO,
514 | BootstrapDialog.TYPE_PRIMARY,
515 | BootstrapDialog.TYPE_SUCCESS,
516 | BootstrapDialog.TYPE_WARNING,
517 | BootstrapDialog.TYPE_DANGER];
518 |
519 | this.getModal().removeClass(types.join(' ')).addClass(this.getType());
520 | }
521 |
522 | return this;
523 | },
524 | getSize: function () {
525 | return this.options.size;
526 | },
527 | setSize: function (size) {
528 | this.options.size = size;
529 | this.updateSize();
530 |
531 | return this;
532 | },
533 | updateSize: function () {
534 | if (this.isRealized()) {
535 | var dialog = this;
536 |
537 | // Dialog size
538 | this.getModal().removeClass(BootstrapDialog.SIZE_NORMAL)
539 | .removeClass(BootstrapDialog.SIZE_SMALL)
540 | .removeClass(BootstrapDialog.SIZE_WIDE)
541 | .removeClass(BootstrapDialog.SIZE_LARGE);
542 | this.getModal().addClass(this.getSize());
543 |
544 | // Smaller dialog.
545 | this.getModalDialog().removeClass('modal-sm');
546 | if (this.getSize() === BootstrapDialog.SIZE_SMALL) {
547 | this.getModalDialog().addClass('modal-sm');
548 | }
549 |
550 | // Wider dialog.
551 | this.getModalDialog().removeClass('modal-lg');
552 | if (this.getSize() === BootstrapDialog.SIZE_WIDE) {
553 | this.getModalDialog().addClass('modal-lg');
554 | }
555 |
556 | // Button size
557 | $.each(this.options.buttons, function (index, button) {
558 | var $button = dialog.getButton(button.id);
559 | var buttonSizes = ['btn-lg', 'btn-sm', 'btn-xs'];
560 | var sizeClassSpecified = false;
561 | if (typeof button['cssClass'] === 'string') {
562 | var btnClasses = button['cssClass'].split(' ');
563 | $.each(btnClasses, function (index, btnClass) {
564 | if ($.inArray(btnClass, buttonSizes) !== -1) {
565 | sizeClassSpecified = true;
566 | }
567 | });
568 | }
569 | if (!sizeClassSpecified) {
570 | $button.removeClass(buttonSizes.join(' '));
571 | $button.addClass(dialog.getButtonSize());
572 | }
573 | });
574 | }
575 |
576 | return this;
577 | },
578 | getCssClass: function () {
579 | return this.options.cssClass;
580 | },
581 | setCssClass: function (cssClass) {
582 | this.options.cssClass = cssClass;
583 |
584 | return this;
585 | },
586 | getTitle: function () {
587 | return this.options.title;
588 | },
589 | setTitle: function (title) {
590 | this.options.title = title;
591 | this.updateTitle();
592 |
593 | return this;
594 | },
595 | updateTitle: function () {
596 | if (this.isRealized()) {
597 | var title = this.getTitle() !== null ? this.createDynamicContent(this.getTitle()) : this.getDefaultText();
598 | this.getModalHeader().find('.' + this.getNamespace('title')).html('').append(title).prop('id', this.getId() + '_title');
599 | }
600 |
601 | return this;
602 | },
603 | getMessage: function () {
604 | return this.options.message;
605 | },
606 | setMessage: function (message) {
607 | this.options.message = message;
608 | this.updateMessage();
609 |
610 | return this;
611 | },
612 | updateMessage: function () {
613 | if (this.isRealized()) {
614 | var message = this.createDynamicContent(this.getMessage());
615 | this.getModalBody().find('.' + this.getNamespace('message')).html('').append(message);
616 | }
617 |
618 | return this;
619 | },
620 | isClosable: function () {
621 | return this.options.closable;
622 | },
623 | setClosable: function (closable) {
624 | this.options.closable = closable;
625 | this.updateClosable();
626 |
627 | return this;
628 | },
629 | setCloseByBackdrop: function (closeByBackdrop) {
630 | this.options.closeByBackdrop = closeByBackdrop;
631 |
632 | return this;
633 | },
634 | canCloseByBackdrop: function () {
635 | return this.options.closeByBackdrop;
636 | },
637 | setCloseByKeyboard: function (closeByKeyboard) {
638 | this.options.closeByKeyboard = closeByKeyboard;
639 |
640 | return this;
641 | },
642 | canCloseByKeyboard: function () {
643 | return this.options.closeByKeyboard;
644 | },
645 | isAnimate: function () {
646 | return this.options.animate;
647 | },
648 | setAnimate: function (animate) {
649 | this.options.animate = animate;
650 |
651 | return this;
652 | },
653 | updateAnimate: function () {
654 | if (this.isRealized()) {
655 | this.getModal().toggleClass('fade', this.isAnimate());
656 | }
657 |
658 | return this;
659 | },
660 | getSpinicon: function () {
661 | return this.options.spinicon;
662 | },
663 | setSpinicon: function (spinicon) {
664 | this.options.spinicon = spinicon;
665 |
666 | return this;
667 | },
668 | addButton: function (button) {
669 | this.options.buttons.push(button);
670 |
671 | return this;
672 | },
673 | addButtons: function (buttons) {
674 | var that = this;
675 | $.each(buttons, function (index, button) {
676 | that.addButton(button);
677 | });
678 |
679 | return this;
680 | },
681 | getButtons: function () {
682 | return this.options.buttons;
683 | },
684 | setButtons: function (buttons) {
685 | this.options.buttons = buttons;
686 | this.updateButtons();
687 |
688 | return this;
689 | },
690 | /**
691 | * If there is id provided for a button option, it will be in dialog.indexedButtons list.
692 | *
693 | * In that case you can use dialog.getButton(id) to find the button.
694 | *
695 | * @param {type} id
696 | * @returns {undefined}
697 | */
698 | getButton: function (id) {
699 | if (typeof this.indexedButtons[id] !== 'undefined') {
700 | return this.indexedButtons[id];
701 | }
702 |
703 | return null;
704 | },
705 | getButtonSize: function () {
706 | if (typeof BootstrapDialog.BUTTON_SIZES[this.getSize()] !== 'undefined') {
707 | return BootstrapDialog.BUTTON_SIZES[this.getSize()];
708 | }
709 |
710 | return '';
711 | },
712 | updateButtons: function () {
713 | if (this.isRealized()) {
714 | if (this.getButtons().length === 0) {
715 | this.getModalFooter().hide();
716 | } else {
717 | this.getModalFooter().show().find('.' + this.getNamespace('footer')).html('').append(this.createFooterButtons());
718 | }
719 | }
720 |
721 | return this;
722 | },
723 | isAutodestroy: function () {
724 | return this.options.autodestroy;
725 | },
726 | setAutodestroy: function (autodestroy) {
727 | this.options.autodestroy = autodestroy;
728 | },
729 | getDescription: function () {
730 | return this.options.description;
731 | },
732 | setDescription: function (description) {
733 | this.options.description = description;
734 |
735 | return this;
736 | },
737 | setTabindex: function (tabindex) {
738 | this.options.tabindex = tabindex;
739 |
740 | return this;
741 | },
742 | getTabindex: function () {
743 | return this.options.tabindex;
744 | },
745 | updateTabindex: function () {
746 | if (this.isRealized()) {
747 | this.getModal().attr('tabindex', this.getTabindex());
748 | }
749 |
750 | return this;
751 | },
752 | getDefaultText: function () {
753 | return BootstrapDialog.DEFAULT_TEXTS[this.getType()];
754 | },
755 | getNamespace: function (name) {
756 | return BootstrapDialog.NAMESPACE + '-' + name;
757 | },
758 | createHeaderContent: function () {
759 | var $container = $('
');
760 | $container.addClass(this.getNamespace('header'));
761 |
762 | // title
763 | $container.append(this.createTitleContent());
764 |
765 | // Close button
766 | $container.prepend(this.createCloseButton());
767 |
768 | return $container;
769 | },
770 | createTitleContent: function () {
771 | var $title = $('
');
772 | $title.addClass(this.getNamespace('title'));
773 |
774 | return $title;
775 | },
776 | createCloseButton: function () {
777 | var $container = $('
');
778 | $container.addClass(this.getNamespace('close-button'));
779 | var $icon = $(' ');
780 | $icon.append(this.options.closeIcon);
781 | $container.append($icon);
782 | $container.on('click', {dialog: this}, function (event) {
783 | event.data.dialog.close();
784 | });
785 |
786 | return $container;
787 | },
788 | createBodyContent: function () {
789 | var $container = $('
');
790 | $container.addClass(this.getNamespace('body'));
791 |
792 | // Message
793 | $container.append(this.createMessageContent());
794 |
795 | return $container;
796 | },
797 | createMessageContent: function () {
798 | var $message = $('
');
799 | $message.addClass(this.getNamespace('message'));
800 |
801 | return $message;
802 | },
803 | createFooterContent: function () {
804 | var $container = $('
');
805 | $container.addClass(this.getNamespace('footer'));
806 |
807 | return $container;
808 | },
809 | createFooterButtons: function () {
810 | var that = this;
811 | var $container = $('
');
812 | $container.addClass(this.getNamespace('footer-buttons'));
813 | this.indexedButtons = {};
814 | $.each(this.options.buttons, function (index, button) {
815 | if (!button.id) {
816 | button.id = BootstrapDialog.newGuid();
817 | }
818 | var $button = that.createButton(button);
819 | that.indexedButtons[button.id] = $button;
820 | $container.append($button);
821 | });
822 |
823 | return $container;
824 | },
825 | createButton: function (button) {
826 | var $button = $(' ');
827 | $button.prop('id', button.id);
828 | $button.data('button', button);
829 |
830 | // Icon
831 | if (typeof button.icon !== 'undefined' && $.trim(button.icon) !== '') {
832 | $button.append(this.createButtonIcon(button.icon));
833 | }
834 |
835 | // Label
836 | if (typeof button.label !== 'undefined') {
837 | $button.append(button.label);
838 | }
839 |
840 | // title
841 | if (typeof button.title !== 'undefined') {
842 | $button.attr('title', button.title);
843 | }
844 |
845 | // Css class
846 | if (typeof button.cssClass !== 'undefined' && $.trim(button.cssClass) !== '') {
847 | $button.addClass(button.cssClass);
848 | } else {
849 | $button.addClass('btn-default');
850 | }
851 |
852 | // Data attributes
853 | if (typeof button.data === 'object' && button.data.constructor === {}.constructor) {
854 | $.each(button.data, function (key, value) {
855 | $button.attr('data-' + key, value);
856 | });
857 | }
858 |
859 | // Hotkey
860 | if (typeof button.hotkey !== 'undefined') {
861 | this.registeredButtonHotkeys[button.hotkey] = $button;
862 | }
863 |
864 | // Button on click
865 | $button.on('click', {dialog: this, $button: $button, button: button}, function (event) {
866 | var dialog = event.data.dialog;
867 | var $button = event.data.$button;
868 | var button = $button.data('button');
869 | if (button.autospin) {
870 | $button.toggleSpin(true);
871 | }
872 | if (typeof button.action === 'function') {
873 | return button.action.call($button, dialog, event);
874 | }
875 | });
876 |
877 | // Dynamically add extra functions to $button
878 | this.enhanceButton($button);
879 |
880 | //Initialize enabled or not
881 | if (typeof button.enabled !== 'undefined') {
882 | $button.toggleEnable(button.enabled);
883 | }
884 |
885 | return $button;
886 | },
887 | /**
888 | * Dynamically add extra functions to $button
889 | *
890 | * Using '$this' to reference 'this' is just for better readability.
891 | *
892 | * @param {type} $button
893 | * @returns {_L13.BootstrapDialog.prototype}
894 | */
895 | enhanceButton: function ($button) {
896 | $button.dialog = this;
897 |
898 | // Enable / Disable
899 | $button.toggleEnable = function (enable) {
900 | var $this = this;
901 | if (typeof enable !== 'undefined') {
902 | $this.prop("disabled", !enable).toggleClass('disabled', !enable);
903 | } else {
904 | $this.prop("disabled", !$this.prop("disabled"));
905 | }
906 |
907 | return $this;
908 | };
909 | $button.enable = function () {
910 | var $this = this;
911 | $this.toggleEnable(true);
912 |
913 | return $this;
914 | };
915 | $button.disable = function () {
916 | var $this = this;
917 | $this.toggleEnable(false);
918 |
919 | return $this;
920 | };
921 |
922 | // Icon spinning, helpful for indicating ajax loading status.
923 | $button.toggleSpin = function (spin) {
924 | var $this = this;
925 | var dialog = $this.dialog;
926 | var $icon = $this.find('.' + dialog.getNamespace('button-icon'));
927 | if (typeof spin === 'undefined') {
928 | spin = !($button.find('.icon-spin').length > 0);
929 | }
930 | if (spin) {
931 | $icon.hide();
932 | $button.prepend(dialog.createButtonIcon(dialog.getSpinicon()).addClass('icon-spin'));
933 | } else {
934 | $icon.show();
935 | $button.find('.icon-spin').remove();
936 | }
937 |
938 | return $this;
939 | };
940 | $button.spin = function () {
941 | var $this = this;
942 | $this.toggleSpin(true);
943 |
944 | return $this;
945 | };
946 | $button.stopSpin = function () {
947 | var $this = this;
948 | $this.toggleSpin(false);
949 |
950 | return $this;
951 | };
952 |
953 | return this;
954 | },
955 | createButtonIcon: function (icon) {
956 | var $icon = $(' ');
957 | $icon.addClass(this.getNamespace('button-icon')).addClass(icon);
958 |
959 | return $icon;
960 | },
961 | /**
962 | * Invoke this only after the dialog is realized.
963 | *
964 | * @param {type} enable
965 | * @returns {undefined}
966 | */
967 | enableButtons: function (enable) {
968 | $.each(this.indexedButtons, function (id, $button) {
969 | $button.toggleEnable(enable);
970 | });
971 |
972 | return this;
973 | },
974 | /**
975 | * Invoke this only after the dialog is realized.
976 | *
977 | * @returns {undefined}
978 | */
979 | updateClosable: function () {
980 | if (this.isRealized()) {
981 | // Close button
982 | this.getModalHeader().find('.' + this.getNamespace('close-button')).toggle(this.isClosable());
983 | }
984 |
985 | return this;
986 | },
987 | /**
988 | * Set handler for modal event 'show.bs.modal'.
989 | * This is a setter!
990 | */
991 | onShow: function (onshow) {
992 | this.options.onshow = onshow;
993 |
994 | return this;
995 | },
996 | /**
997 | * Set handler for modal event 'shown.bs.modal'.
998 | * This is a setter!
999 | */
1000 | onShown: function (onshown) {
1001 | this.options.onshown = onshown;
1002 |
1003 | return this;
1004 | },
1005 | /**
1006 | * Set handler for modal event 'hide.bs.modal'.
1007 | * This is a setter!
1008 | */
1009 | onHide: function (onhide) {
1010 | this.options.onhide = onhide;
1011 |
1012 | return this;
1013 | },
1014 | /**
1015 | * Set handler for modal event 'hidden.bs.modal'.
1016 | * This is a setter!
1017 | */
1018 | onHidden: function (onhidden) {
1019 | this.options.onhidden = onhidden;
1020 |
1021 | return this;
1022 | },
1023 | isRealized: function () {
1024 | return this.realized;
1025 | },
1026 | setRealized: function (realized) {
1027 | this.realized = realized;
1028 |
1029 | return this;
1030 | },
1031 | isOpened: function () {
1032 | return this.opened;
1033 | },
1034 | setOpened: function (opened) {
1035 | this.opened = opened;
1036 |
1037 | return this;
1038 | },
1039 | handleModalEvents: function () {
1040 | this.getModal().on('show.bs.modal', {dialog: this}, function (event) {
1041 | var dialog = event.data.dialog;
1042 | dialog.setOpened(true);
1043 | if (dialog.isModalEvent(event) && typeof dialog.options.onshow === 'function') {
1044 | var openIt = dialog.options.onshow(dialog);
1045 | if (openIt === false) {
1046 | dialog.setOpened(false);
1047 | }
1048 |
1049 | return openIt;
1050 | }
1051 | });
1052 | this.getModal().on('shown.bs.modal', {dialog: this}, function (event) {
1053 | var dialog = event.data.dialog;
1054 | dialog.isModalEvent(event) && typeof dialog.options.onshown === 'function' && dialog.options.onshown(dialog);
1055 | });
1056 | this.getModal().on('hide.bs.modal', {dialog: this}, function (event) {
1057 | var dialog = event.data.dialog;
1058 | dialog.setOpened(false);
1059 | if (dialog.isModalEvent(event) && typeof dialog.options.onhide === 'function') {
1060 | var hideIt = dialog.options.onhide(dialog);
1061 | if (hideIt === false) {
1062 | dialog.setOpened(true);
1063 | }
1064 |
1065 | return hideIt;
1066 | }
1067 | });
1068 | this.getModal().on('hidden.bs.modal', {dialog: this}, function (event) {
1069 | var dialog = event.data.dialog;
1070 | dialog.isModalEvent(event) && typeof dialog.options.onhidden === 'function' && dialog.options.onhidden(dialog);
1071 | if (dialog.isAutodestroy()) {
1072 | dialog.setRealized(false);
1073 | delete BootstrapDialog.dialogs[dialog.getId()];
1074 | $(this).remove();
1075 | }
1076 | BootstrapDialog.moveFocus();
1077 | if ($('.modal').hasClass('in')) {
1078 | $('body').addClass('modal-open');
1079 | }
1080 | });
1081 |
1082 | // Backdrop, I did't find a way to change bs3 backdrop option after the dialog is popped up, so here's a new wheel.
1083 | this.handleModalBackdropEvent();
1084 |
1085 | // ESC key support
1086 | this.getModal().on('keyup', {dialog: this}, function (event) {
1087 | event.which === 27 && event.data.dialog.isClosable() && event.data.dialog.canCloseByKeyboard() && event.data.dialog.close();
1088 | });
1089 |
1090 | // Button hotkey
1091 | this.getModal().on('keyup', {dialog: this}, function (event) {
1092 | var dialog = event.data.dialog;
1093 | if (typeof dialog.registeredButtonHotkeys[event.which] !== 'undefined') {
1094 | var $button = $(dialog.registeredButtonHotkeys[event.which]);
1095 | !$button.prop('disabled') && !$button.is(':focus') && $button.focus().trigger('click');
1096 | }
1097 | });
1098 |
1099 | return this;
1100 | },
1101 | handleModalBackdropEvent: function () {
1102 | this.getModal().on('click', {dialog: this}, function (event) {
1103 | $(event.target).hasClass('modal-backdrop') && event.data.dialog.isClosable() && event.data.dialog.canCloseByBackdrop() && event.data.dialog.close();
1104 | });
1105 |
1106 | return this;
1107 | },
1108 | isModalEvent: function (event) {
1109 | return typeof event.namespace !== 'undefined' && event.namespace === 'bs.modal';
1110 | },
1111 | makeModalDraggable: function () {
1112 | if (this.options.draggable) {
1113 | this.getModalHeader().addClass(this.getNamespace('draggable')).on('mousedown', {dialog: this}, function (event) {
1114 | var dialog = event.data.dialog;
1115 | dialog.draggableData.isMouseDown = true;
1116 | var dialogOffset = dialog.getModalDialog().offset();
1117 | dialog.draggableData.mouseOffset = {
1118 | top: event.clientY - dialogOffset.top,
1119 | left: event.clientX - dialogOffset.left
1120 | };
1121 | });
1122 | this.getModal().on('mouseup mouseleave', {dialog: this}, function (event) {
1123 | event.data.dialog.draggableData.isMouseDown = false;
1124 | });
1125 | $('body').on('mousemove', {dialog: this}, function (event) {
1126 | var dialog = event.data.dialog;
1127 | if (!dialog.draggableData.isMouseDown) {
1128 | return;
1129 | }
1130 | dialog.getModalDialog().offset({
1131 | top: event.clientY - dialog.draggableData.mouseOffset.top,
1132 | left: event.clientX - dialog.draggableData.mouseOffset.left
1133 | });
1134 | });
1135 | }
1136 |
1137 | return this;
1138 | },
1139 | realize: function () {
1140 | this.initModalStuff();
1141 | this.getModal().addClass(BootstrapDialog.NAMESPACE)
1142 | .addClass(this.getCssClass());
1143 | this.updateSize();
1144 | if (this.getDescription()) {
1145 | this.getModal().attr('aria-describedby', this.getDescription());
1146 | }
1147 | this.getModalFooter().append(this.createFooterContent());
1148 | this.getModalHeader().append(this.createHeaderContent());
1149 | this.getModalBody().append(this.createBodyContent());
1150 | this.getModal().data('bs.modal', new BootstrapDialogModal(this.getModal(), {
1151 | backdrop: 'static',
1152 | keyboard: false,
1153 | show: false
1154 | }));
1155 | this.makeModalDraggable();
1156 | this.handleModalEvents();
1157 | this.setRealized(true);
1158 | this.updateButtons();
1159 | this.updateType();
1160 | this.updateTitle();
1161 | this.updateMessage();
1162 | this.updateClosable();
1163 | this.updateAnimate();
1164 | this.updateSize();
1165 | this.updateTabindex();
1166 |
1167 | return this;
1168 | },
1169 | open: function () {
1170 | !this.isRealized() && this.realize();
1171 | this.getModal().modal('show');
1172 |
1173 | return this;
1174 | },
1175 | close: function () {
1176 | !this.isRealized() && this.realize();
1177 | this.getModal().modal('hide');
1178 |
1179 | return this;
1180 | }
1181 | };
1182 |
1183 | // Add compatible methods.
1184 | BootstrapDialog.prototype = $.extend(BootstrapDialog.prototype, BootstrapDialog.METHODS_TO_OVERRIDE[BootstrapDialogModal.getModalVersion()]);
1185 |
1186 | /**
1187 | * RFC4122 version 4 compliant unique id creator.
1188 | *
1189 | * Added by https://github.com/tufanbarisyildirim/
1190 | *
1191 | * @returns {String}
1192 | */
1193 | BootstrapDialog.newGuid = function () {
1194 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
1195 | var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
1196 | return v.toString(16);
1197 | });
1198 | };
1199 |
1200 | /* ================================================
1201 | * For lazy people
1202 | * ================================================ */
1203 |
1204 | /**
1205 | * Shortcut function: show
1206 | *
1207 | * @param {type} options
1208 | * @returns the created dialog instance
1209 | */
1210 | BootstrapDialog.show = function (options) {
1211 | return new BootstrapDialog(options).open();
1212 | };
1213 |
1214 | /**
1215 | * Alert window
1216 | *
1217 | * @returns the created dialog instance
1218 | */
1219 | BootstrapDialog.alert = function () {
1220 | var alertOptions = {};
1221 | var defaultAlertOptions = {
1222 | type: BootstrapDialog.TYPE_PRIMARY,
1223 | title: null,
1224 | message: null,
1225 | closable: false,
1226 | draggable: false,
1227 | buttonLabel: BootstrapDialog.DEFAULT_TEXTS.OK,
1228 | buttonHotkey: null,
1229 | callback: null
1230 | };
1231 |
1232 | if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
1233 | alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
1234 | } else {
1235 | alertOptions = $.extend(true, defaultAlertOptions, {
1236 | message: arguments[0],
1237 | callback: typeof arguments[1] !== 'undefined' ? arguments[1] : null
1238 | });
1239 | }
1240 |
1241 | var dialog = new BootstrapDialog(alertOptions);
1242 | dialog.setData('callback', alertOptions.callback);
1243 | dialog.addButton({
1244 | label: alertOptions.buttonLabel,
1245 | hotkey: alertOptions.buttonHotkey,
1246 | action: function (dialog) {
1247 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, true) === false) {
1248 | return false;
1249 | }
1250 | dialog.setData('btnClicked', true);
1251 |
1252 | return dialog.close();
1253 | }
1254 | });
1255 | if (typeof dialog.options.onhide === 'function') {
1256 | dialog.onHide(function (dialog) {
1257 | var hideIt = true;
1258 | if (!dialog.getData('btnClicked') && dialog.isClosable() && typeof dialog.getData('callback') === 'function') {
1259 | hideIt = dialog.getData('callback')(false);
1260 | }
1261 | if (hideIt === false) {
1262 | return false;
1263 | }
1264 | hideIt = this.onhide(dialog);
1265 |
1266 | return hideIt;
1267 | }.bind({
1268 | onhide: dialog.options.onhide
1269 | }));
1270 | } else {
1271 | dialog.onHide(function (dialog) {
1272 | var hideIt = true;
1273 | if (!dialog.getData('btnClicked') && dialog.isClosable() && typeof dialog.getData('callback') === 'function') {
1274 | hideIt = dialog.getData('callback')(false);
1275 | }
1276 |
1277 | return hideIt;
1278 | });
1279 | }
1280 |
1281 | return dialog.open();
1282 | };
1283 |
1284 | /**
1285 | * Confirm window
1286 | *
1287 | * @returns the created dialog instance
1288 | */
1289 | BootstrapDialog.confirm = function () {
1290 | var confirmOptions = {};
1291 | var defaultConfirmOptions = {
1292 | type: BootstrapDialog.TYPE_PRIMARY,
1293 | title: null,
1294 | message: null,
1295 | closable: false,
1296 | draggable: false,
1297 | btnCancelLabel: BootstrapDialog.DEFAULT_TEXTS.CANCEL,
1298 | btnCancelClass: null,
1299 | btnCancelHotkey: null,
1300 | btnOKLabel: BootstrapDialog.DEFAULT_TEXTS.OK,
1301 | btnOKClass: null,
1302 | btnOKHotkey: null,
1303 | btnsOrder: BootstrapDialog.defaultOptions.btnsOrder,
1304 | callback: null
1305 | };
1306 | if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
1307 | confirmOptions = $.extend(true, defaultConfirmOptions, arguments[0]);
1308 | } else {
1309 | confirmOptions = $.extend(true, defaultConfirmOptions, {
1310 | message: arguments[0],
1311 | callback: typeof arguments[1] !== 'undefined' ? arguments[1] : null
1312 | });
1313 | }
1314 | if (confirmOptions.btnOKClass === null) {
1315 | confirmOptions.btnOKClass = ['btn', confirmOptions.type.split('-')[1]].join('-');
1316 | }
1317 |
1318 | var dialog = new BootstrapDialog(confirmOptions);
1319 | dialog.setData('callback', confirmOptions.callback);
1320 |
1321 | var buttons = [{
1322 | label: confirmOptions.btnCancelLabel,
1323 | cssClass: confirmOptions.btnCancelClass,
1324 | hotkey: confirmOptions.btnCancelHotkey,
1325 | action: function (dialog) {
1326 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, false) === false) {
1327 | return false;
1328 | }
1329 |
1330 | return dialog.close();
1331 | }
1332 | }, {
1333 | label: confirmOptions.btnOKLabel,
1334 | cssClass: confirmOptions.btnOKClass,
1335 | hotkey: confirmOptions.btnOKHotkey,
1336 | action: function (dialog) {
1337 | if (typeof dialog.getData('callback') === 'function' && dialog.getData('callback').call(this, true) === false) {
1338 | return false;
1339 | }
1340 |
1341 | return dialog.close();
1342 | }
1343 | }];
1344 | if (confirmOptions.btnsOrder === BootstrapDialog.BUTTONS_ORDER_OK_CANCEL) {
1345 | buttons.reverse();
1346 | }
1347 | dialog.addButtons(buttons);
1348 |
1349 | return dialog.open();
1350 |
1351 | };
1352 |
1353 | /**
1354 | * Warning window
1355 | *
1356 | * @param {type} message
1357 | * @returns the created dialog instance
1358 | */
1359 | BootstrapDialog.warning = function (message, callback) {
1360 | return new BootstrapDialog({
1361 | type: BootstrapDialog.TYPE_WARNING,
1362 | message: message
1363 | }).open();
1364 | };
1365 |
1366 | /**
1367 | * Danger window
1368 | *
1369 | * @param {type} message
1370 | * @returns the created dialog instance
1371 | */
1372 | BootstrapDialog.danger = function (message, callback) {
1373 | return new BootstrapDialog({
1374 | type: BootstrapDialog.TYPE_DANGER,
1375 | message: message
1376 | }).open();
1377 | };
1378 |
1379 | /**
1380 | * Success window
1381 | *
1382 | * @param {type} message
1383 | * @returns the created dialog instance
1384 | */
1385 | BootstrapDialog.success = function (message, callback) {
1386 | return new BootstrapDialog({
1387 | type: BootstrapDialog.TYPE_SUCCESS,
1388 | message: message
1389 | }).open();
1390 | };
1391 |
1392 | return BootstrapDialog;
1393 |
1394 | }));
1395 |
--------------------------------------------------------------------------------
/src/less/bootstrap-dialog.less:
--------------------------------------------------------------------------------
1 | .bootstrap-dialog {
2 |
3 | .modal-header {
4 | border-top-left-radius: 4px;
5 | border-top-right-radius: 4px;
6 | }
7 | .bootstrap-dialog-title {
8 | color: #fff;
9 | display: inline-block;
10 | font-size: 16px;
11 | }
12 | .bootstrap-dialog-message {
13 | font-size: 14px;
14 | }
15 | .bootstrap-dialog-button-icon {
16 | margin-right: 3px;
17 | }
18 | .bootstrap-dialog-close-button {
19 | font-size: 20px;
20 | float: right;
21 | .opacity(0.9);
22 | &:hover {
23 | cursor: pointer;
24 | .opacity(1.0);
25 | }
26 | }
27 |
28 | /* dialog types */
29 | &.type-default {
30 | .modal-header {
31 | background-color: @modal-content-bg;
32 | }
33 | .bootstrap-dialog-title {
34 | color: #333;
35 | }
36 | }
37 |
38 | &.type-info {
39 | .modal-header {
40 | background-color: @brand-info;
41 | }
42 | }
43 |
44 | &.type-primary {
45 | .modal-header {
46 | background-color: @brand-primary;
47 | }
48 | }
49 |
50 | &.type-success {
51 | .modal-header {
52 | background-color: @brand-success;
53 | }
54 | }
55 |
56 | &.type-warning {
57 | .modal-header {
58 | background-color: @brand-warning;
59 | }
60 | }
61 |
62 | &.type-danger {
63 | .modal-header {
64 | background-color: @brand-danger;
65 | }
66 | }
67 |
68 | &.size-large {
69 | .bootstrap-dialog-title {
70 | font-size: 24px;
71 | }
72 | .bootstrap-dialog-close-button {
73 | font-size: 30px;
74 | }
75 | .bootstrap-dialog-message {
76 | font-size: 18px;
77 | }
78 | }
79 |
80 | /**
81 | * Icon animation
82 | * Copied from font-awesome: http://fontawesome.io/
83 | **/
84 | .icon-spin {
85 | display: inline-block;
86 | -moz-animation: spin 2s infinite linear;
87 | -o-animation: spin 2s infinite linear;
88 | -webkit-animation: spin 2s infinite linear;
89 | animation: spin 2s infinite linear;
90 | }
91 | @-moz-keyframes spin {
92 | 0% {
93 | -moz-transform: rotate(0deg);
94 | }
95 | 100% {
96 | -moz-transform: rotate(359deg);
97 | }
98 | }
99 | @-webkit-keyframes spin {
100 | 0% {
101 | -webkit-transform: rotate(0deg);
102 | }
103 | 100% {
104 | -webkit-transform: rotate(359deg);
105 | }
106 | }
107 | @-o-keyframes spin {
108 | 0% {
109 | -o-transform: rotate(0deg);
110 | }
111 | 100% {
112 | -o-transform: rotate(359deg);
113 | }
114 | }
115 | @-ms-keyframes spin {
116 | 0% {
117 | -ms-transform: rotate(0deg);
118 | }
119 | 100% {
120 | -ms-transform: rotate(359deg);
121 | }
122 | }
123 | @keyframes spin {
124 | 0% {
125 | transform: rotate(0deg);
126 | }
127 | 100% {
128 | transform: rotate(359deg);
129 | }
130 | }
131 | /** End of icon animation **/
132 | }
133 |
--------------------------------------------------------------------------------