bootstrap_modal_rails 2.0.4 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
- /* ===========================================================
2
- * bootstrap-modalmanager.js v2.0
1
+ /* ===========================================================
2
+ * bootstrap-modalmanager.js v2.1
3
3
  * ===========================================================
4
4
  * Copyright 2012 Jordan Schroter.
5
5
  *
@@ -18,353 +18,389 @@
18
18
 
19
19
  !function ($) {
20
20
 
21
- "use strict"; // jshint ;_;
21
+ "use strict"; // jshint ;_;
22
22
 
23
- /* MODAL MANAGER CLASS DEFINITION
24
- * ====================== */
23
+ /* MODAL MANAGER CLASS DEFINITION
24
+ * ====================== */
25
25
 
26
- var ModalManager = function (element, options) {
27
- this.init(element, options);
28
- }
26
+ var ModalManager = function (element, options) {
27
+ this.init(element, options);
28
+ };
29
29
 
30
- ModalManager.prototype = {
30
+ ModalManager.prototype = {
31
31
 
32
- constructor: ModalManager,
32
+ constructor: ModalManager,
33
33
 
34
- init: function (element, options) {
35
- this.$element = $(element);
36
- this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options == 'object' && options);
37
- this.stack = [];
38
- this.backdropCount = 0;
39
- },
34
+ init: function (element, options) {
35
+ this.$element = $(element);
36
+ this.options = $.extend({}, $.fn.modalmanager.defaults, this.$element.data(), typeof options == 'object' && options);
37
+ this.stack = [];
38
+ this.backdropCount = 0;
40
39
 
41
- createModal: function (element, options) {
42
- $(element).modal($.extend({ manager: this }, options));
43
- },
40
+ if (this.options.resize) {
41
+ var resizeTimeout,
42
+ that = this;
44
43
 
45
- appendModal: function (modal) {
46
- this.stack.push(modal);
44
+ $(window).on('resize.modal', function(){
45
+ resizeTimeout && clearTimeout(resizeTimeout);
46
+ resizeTimeout = setTimeout(function(){
47
+ for (var i = 0; i < that.stack.length; i++){
48
+ that.stack[i].isShown && that.stack[i].layout();
49
+ }
50
+ }, 10);
51
+ });
52
+ }
53
+ },
47
54
 
48
- var that = this;
55
+ createModal: function (element, options) {
56
+ $(element).modal($.extend({ manager: this }, options));
57
+ },
49
58
 
50
- modal.$element.on('show.modalmanager', targetIsSelf(function (e) {
51
- modal.isShown = true;
59
+ appendModal: function (modal) {
60
+ this.stack.push(modal);
52
61
 
53
- var transition = $.support.transition && modal.$element.hasClass('fade');
54
-
55
- that.$element
56
- .toggleClass('modal-open', that.hasOpenModal())
57
- .toggleClass('page-overflow', $(window).height() < that.$element.height());
58
-
59
- modal.$parent = modal.$element.parent();
60
-
61
- modal.$container = that.createContainer(modal);
62
+ var that = this;
62
63
 
63
- modal.$element.appendTo(modal.$container);
64
+ modal.$element.on('show.modalmanager', targetIsSelf(function (e) {
64
65
 
65
- var modalOverflow = $(window).height() < modal.$element.height() || modal.options.modalOverflow;
66
-
67
- that.backdrop(modal, function () {
66
+ var showModal = function(){
67
+ modal.isShown = true;
68
68
 
69
- modal.$element.show();
69
+ var transition = $.support.transition && modal.$element.hasClass('fade');
70
70
 
71
- if (transition) {
72
- modal.$element[0].style.display = 'run-in';
73
- modal.$element[0].offsetWidth;
74
- modal.$element.one($.support.transition.end, function () { modal.$element[0].style.display = 'block' });
75
- }
71
+ that.$element
72
+ .toggleClass('modal-open', that.hasOpenModal())
73
+ .toggleClass('page-overflow', $(window).height() < that.$element.height());
76
74
 
77
- modal.$element
78
- .toggleClass('modal-overflow', modalOverflow)
79
- .css('margin-top', modalOverflow ? 0 : 0 - modal.$element.height()/2)
80
- .addClass('in')
81
- .attr('aria-hidden', false);
82
-
83
- var complete = function () {
84
- that.setFocus();
85
- modal.$element.triggerHandler('shown');
86
- }
75
+ modal.$parent = modal.$element.parent();
87
76
 
88
- transition ?
89
- modal.$element.one($.support.transition.end, complete) :
90
- complete();
91
- });
92
- }));
77
+ modal.$container = that.createContainer(modal);
93
78
 
94
- modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
79
+ modal.$element.appendTo(modal.$container);
95
80
 
96
- that.backdrop(modal);
81
+ that.backdrop(modal, function () {
97
82
 
98
- if (modal.$backdrop){
99
- $.support.transition && modal.$element.hasClass('fade')?
100
- modal.$backdrop.one($.support.transition.end, function () { that.destroyModal(modal) }) :
101
- that.destroyModal(modal);
102
- } else {
103
- that.destroyModal(modal);
104
- }
83
+ modal.$element.show();
105
84
 
106
- }));
85
+ modal.layout();
107
86
 
108
- modal.$element.on('destroy.modalmanager', targetIsSelf(function (e) {
109
- that.removeModal(modal);
110
- }));
111
- },
87
+ modal.$element
88
+ .addClass('in')
89
+ .attr('aria-hidden', false);
112
90
 
113
- destroyModal: function (modal) {
91
+ var complete = function () {
92
+ that.setFocus();
93
+ modal.$element.triggerHandler('shown');
94
+ };
114
95
 
115
- modal.destroy();
96
+ transition ?
97
+ modal.$element.one($.support.transition.end, complete) :
98
+ complete();
99
+ });
100
+ };
116
101
 
117
- var hasOpenModal = this.hasOpenModal();
102
+ modal.options.replace ?
103
+ that.replace(showModal) :
104
+ showModal();
105
+ }));
118
106
 
119
- this.$element.toggleClass('modal-open', hasOpenModal);
120
-
121
- if (!hasOpenModal){
122
- this.$element.removeClass('page-overflow');
123
- }
107
+ modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
124
108
 
125
- this.removeContainer(modal);
109
+ that.backdrop(modal);
126
110
 
127
- this.setFocus();
128
- },
111
+ if (modal.$backdrop){
112
+ $.support.transition && modal.$element.hasClass('fade') ?
113
+ modal.$backdrop.one($.support.transition.end, function () { that.destroyModal(modal) }) :
114
+ that.destroyModal(modal);
115
+ } else {
116
+ that.destroyModal(modal);
117
+ }
129
118
 
130
- hasOpenModal: function () {
131
- for (var i = 0; i < this.stack.length; i++){
132
- if (this.stack[i].isShown) return true;
133
- }
119
+ }));
134
120
 
135
- return false;
136
- },
121
+ modal.$element.on('destroy.modalmanager', targetIsSelf(function (e) {
122
+ that.removeModal(modal);
123
+ }));
137
124
 
138
- setFocus: function () {
139
- var topModal;
125
+ },
140
126
 
141
- for (var i = 0; i < this.stack.length; i++){
142
- if (this.stack[i].isShown) topModal = this.stack[i];
143
- }
127
+ destroyModal: function (modal) {
144
128
 
145
- if (!topModal) return;
129
+ modal.destroy();
146
130
 
147
- topModal.focus();
131
+ var hasOpenModal = this.hasOpenModal();
148
132
 
149
- },
133
+ this.$element.toggleClass('modal-open', hasOpenModal);
150
134
 
151
- removeModal: function (modal) {
152
- modal.$element.off('.modalmanager');
153
- if (modal.$backdrop) this.removeBackdrop.call(modal);
154
- this.stack.splice(this.getIndexOfModal(modal), 1);
155
- },
135
+ if (!hasOpenModal){
136
+ this.$element.removeClass('page-overflow');
137
+ }
156
138
 
157
- getModalAt: function (index) {
158
- return this.stack[index];
159
- },
139
+ this.removeContainer(modal);
160
140
 
161
- getIndexOfModal: function (modal) {
162
- for (var i = 0; i < this.stack.length; i++){
163
- if (modal === this.stack[i]) return i;
164
- }
165
- },
166
-
167
- removeBackdrop: function (modal) {
168
- modal.$backdrop.remove();
169
- modal.$backdrop = null;
170
- },
171
-
172
- createBackdrop: function (animate) {
173
- var $backdrop;
174
-
175
- if (!this.isLoading) {
176
- $backdrop = $('<div class="modal-backdrop ' + animate + '" />')
177
- .appendTo(this.$element);
178
-
179
- } else {
180
- $backdrop = this.$loading;
181
- $backdrop.off('.modalmanager');
182
- this.$spinner.remove();
183
- this.isLoading = false;
184
- this.$loading = this.$spinner = null;
185
- }
141
+ this.setFocus();
142
+ },
186
143
 
187
- return $backdrop
188
- },
189
-
190
- removeContainer: function (modal) {
191
- modal.$container.remove();
192
- modal.$container = null;
193
- },
194
-
195
- createContainer: function (modal) {
196
- var $container;
197
-
198
- $container = $('<div class="modal-scrollable">')
199
- .css('z-index', getzIndex( 'modal',
200
- modal ? this.getIndexOfModal(modal) : this.stack.length ))
201
- .appendTo(this.$element);
202
-
203
- if (modal && modal.options.backdrop != 'static') {
204
- $container.on('click.modal', targetIsSelf(function (e) {
205
- modal.hide();
206
- }));
207
- } else if (modal) {
208
- $container.on('click.modal', targetIsSelf(function (e) {
209
- modal.attention();
210
- }));
211
- }
144
+ hasOpenModal: function () {
145
+ for (var i = 0; i < this.stack.length; i++){
146
+ if (this.stack[i].isShown) return true;
147
+ }
212
148
 
213
- return $container;
149
+ return false;
150
+ },
214
151
 
215
- },
152
+ setFocus: function () {
153
+ var topModal;
216
154
 
217
- backdrop: function (modal, callback) {
218
- var animate = modal.$element.hasClass('fade') ? 'fade' : '',
219
- showBackdrop = modal.options.backdrop &&
220
- this.backdropCount < this.options.backdropLimit;
155
+ for (var i = 0; i < this.stack.length; i++){
156
+ if (this.stack[i].isShown) topModal = this.stack[i];
157
+ }
221
158
 
222
- if (modal.isShown && showBackdrop) {
223
- var doAnimate = $.support.transition && animate && !this.isLoading;
159
+ if (!topModal) return;
224
160
 
161
+ topModal.focus();
225
162
 
226
- modal.$backdrop = this.createBackdrop(animate);
163
+ },
227
164
 
228
- modal.$backdrop.css('z-index', getzIndex( 'backdrop', this.getIndexOfModal(modal) ))
165
+ removeModal: function (modal) {
166
+ modal.$element.off('.modalmanager');
167
+ if (modal.$backdrop) this.removeBackdrop.call(modal);
168
+ this.stack.splice(this.getIndexOfModal(modal), 1);
169
+ },
229
170
 
230
- if (doAnimate) modal.$backdrop[0].offsetWidth // force reflow
171
+ getModalAt: function (index) {
172
+ return this.stack[index];
173
+ },
231
174
 
232
- modal.$backdrop.addClass('in')
175
+ getIndexOfModal: function (modal) {
176
+ for (var i = 0; i < this.stack.length; i++){
177
+ if (modal === this.stack[i]) return i;
178
+ }
179
+ },
233
180
 
234
- this.backdropCount += 1;
181
+ replace: function (callback) {
182
+ var topModal;
235
183
 
236
- doAnimate ?
237
- modal.$backdrop.one($.support.transition.end, callback) :
238
- callback();
184
+ for (var i = 0; i < this.stack.length; i++){
185
+ if (this.stack[i].isShown) topModal = this.stack[i];
186
+ }
239
187
 
240
- } else if (!modal.isShown && modal.$backdrop) {
241
- modal.$backdrop.removeClass('in');
188
+ if (topModal) {
189
+ this.$backdropHandle = topModal.$backdrop;
190
+ topModal.$backdrop = null;
242
191
 
243
- this.backdropCount -= 1;
192
+ callback && topModal.$element.one('hidden',
193
+ targetIsSelf( $.proxy(callback, this) ));
244
194
 
245
- var that = this;
195
+ topModal.hide();
196
+ } else if (callback) {
197
+ callback();
198
+ }
199
+ },
246
200
 
247
- $.support.transition && modal.$element.hasClass('fade')?
248
- modal.$backdrop.one($.support.transition.end, function () { that.removeBackdrop(modal) }) :
249
- that.removeBackdrop(modal);
201
+ removeBackdrop: function (modal) {
202
+ modal.$backdrop.remove();
203
+ modal.$backdrop = null;
204
+ },
250
205
 
251
- } else if (callback) {
252
- callback();
253
- }
254
- },
206
+ createBackdrop: function (animate) {
207
+ var $backdrop;
255
208
 
256
- removeLoading: function () {
257
- this.$loading && this.$loading.remove();
258
- this.$loading = null;
259
- this.isLoading = false;
260
- },
209
+ if (!this.$backdropHandle) {
210
+ $backdrop = $('<div class="modal-backdrop ' + animate + '" />')
211
+ .appendTo(this.$element);
212
+ } else {
213
+ $backdrop = this.$backdropHandle;
214
+ $backdrop.off('.modalmanager');
215
+ this.$backdropHandle = null;
216
+ this.isLoading && this.removeSpinner();
217
+ }
261
218
 
262
- loading: function (callback) {
263
- callback = callback || function () { };
264
-
265
- this.$element
266
- .toggleClass('modal-open', !this.isLoading || this.hasOpenModal())
267
- .toggleClass('page-overflow', $(window).height() < this.$element.height());
268
-
269
- if (!this.isLoading) {
219
+ return $backdrop
220
+ },
270
221
 
271
- this.$loading = this.createBackdrop('fade');
222
+ removeContainer: function (modal) {
223
+ modal.$container.remove();
224
+ modal.$container = null;
225
+ },
272
226
 
273
- this.$loading[0].offsetWidth // force reflow
227
+ createContainer: function (modal) {
228
+ var $container;
274
229
 
275
- this.$loading
276
- .css('z-index', getzIndex('backdrop', this.stack.length))
277
- .addClass('in');
230
+ $container = $('<div class="modal-scrollable">')
231
+ .css('z-index', getzIndex( 'modal',
232
+ modal ? this.getIndexOfModal(modal) : this.stack.length ))
233
+ .appendTo(this.$element);
278
234
 
279
- var $spinner = $(this.options.spinner)
280
- .css('z-index', getzIndex('modal', this.stack.length))
281
- .appendTo(this.$element)
282
- .addClass('in');
235
+ if (modal && modal.options.backdrop != 'static') {
236
+ $container.on('click.modal', targetIsSelf(function (e) {
237
+ modal.hide();
238
+ }));
239
+ } else if (modal) {
240
+ $container.on('click.modal', targetIsSelf(function (e) {
241
+ modal.attention();
242
+ }));
243
+ }
283
244
 
284
- this.$spinner = $(this.createContainer())
285
- .append($spinner)
286
- .on('click.modalmanager', $.proxy(this.loading, this));
245
+ return $container;
287
246
 
288
- this.isLoading = true;
247
+ },
289
248
 
290
- $.support.transition ?
291
- this.$loading.one($.support.transition.end, callback) :
292
- callback();
249
+ backdrop: function (modal, callback) {
250
+ var animate = modal.$element.hasClass('fade') ? 'fade' : '',
251
+ showBackdrop = modal.options.backdrop &&
252
+ this.backdropCount < this.options.backdropLimit;
293
253
 
294
- } else if (this.isLoading && this.$loading) {
295
- this.$loading.removeClass('in');
254
+ if (modal.isShown && showBackdrop) {
255
+ var doAnimate = $.support.transition && animate && !this.$backdropHandle;
296
256
 
297
- if (this.$spinner) this.$spinner.remove();
257
+ modal.$backdrop = this.createBackdrop(animate);
298
258
 
299
- var that = this;
300
- $.support.transition ?
301
- this.$loading.one($.support.transition.end, function () { that.removeLoading() }) :
302
- that.removeLoading();
259
+ modal.$backdrop.css('z-index', getzIndex( 'backdrop', this.getIndexOfModal(modal) ));
303
260
 
304
- } else if (callback) {
305
- callback(this.isLoading);
306
- }
307
- }
308
- }
261
+ if (doAnimate) modal.$backdrop[0].offsetWidth; // force reflow
309
262
 
310
- /* PRIVATE METHODS
311
- * ======================= */
263
+ modal.$backdrop.addClass('in');
312
264
 
313
- // computes and caches the zindexes
314
- var getzIndex = (function () {
315
- var zIndexFactor,
316
- baseIndex = {};
265
+ this.backdropCount += 1;
317
266
 
318
- return function (type, pos) {
267
+ doAnimate ?
268
+ modal.$backdrop.one($.support.transition.end, callback) :
269
+ callback();
319
270
 
320
- if (typeof zIndexFactor === 'undefined'){
321
- var $baseModal = $('<div class="modal hide" />').appendTo('body'),
322
- $baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
271
+ } else if (!modal.isShown && modal.$backdrop) {
272
+ modal.$backdrop.removeClass('in');
323
273
 
324
- baseIndex['modal'] = +$baseModal.css('z-index'),
325
- baseIndex['backdrop'] = +$baseBackdrop.css('z-index'),
326
- zIndexFactor = baseIndex['modal'] - baseIndex['backdrop'];
327
-
328
- $baseModal.remove();
329
- $baseBackdrop.remove();
330
- $baseBackdrop = $baseModal = null;
331
- }
274
+ this.backdropCount -= 1;
332
275
 
333
- return baseIndex[type] + (zIndexFactor * pos);
276
+ var that = this;
334
277
 
335
- }
336
- }())
337
-
338
- // make sure the event target is the modal itself in order to prevent
339
- // other components such as tabsfrom triggering the modal manager.
340
- // if Boostsrap namespaced events, this would not be needed.
341
- function targetIsSelf(callback){
342
- return function (e) {
343
- if (this === e.target){
344
- return callback.apply(this, arguments);
345
- }
346
- }
347
- }
278
+ $.support.transition && modal.$element.hasClass('fade')?
279
+ modal.$backdrop.one($.support.transition.end, function () { that.removeBackdrop(modal) }) :
280
+ that.removeBackdrop(modal);
281
+
282
+ } else if (callback) {
283
+ callback();
284
+ }
285
+ },
286
+
287
+ removeSpinner: function(){
288
+ this.$spinner && this.$spinner.remove();
289
+ this.$spinner = null;
290
+ this.isLoading = false;
291
+ },
292
+
293
+ removeLoading: function () {
294
+ this.$backdropHandle && this.$backdropHandle.remove();
295
+ this.$backdropHandle = null;
296
+ this.removeSpinner();
297
+ },
298
+
299
+ loading: function (callback) {
300
+ callback = callback || function () { };
348
301
 
302
+ this.$element
303
+ .toggleClass('modal-open', !this.isLoading || this.hasOpenModal())
304
+ .toggleClass('page-overflow', $(window).height() < this.$element.height());
349
305
 
350
- /* MODAL MANAGER PLUGIN DEFINITION
351
- * ======================= */
306
+ if (!this.isLoading) {
352
307
 
353
- $.fn.modalmanager = function (option) {
354
- return this.each(function () {
355
- var $this = $(this),
356
- data = $this.data('modalmanager');
308
+ this.$backdropHandle = this.createBackdrop('fade');
357
309
 
358
- if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)))
359
- if (typeof option === 'string') data[option]()
360
- })
310
+ this.$backdropHandle[0].offsetWidth; // force reflow
311
+
312
+ this.$backdropHandle
313
+ .css('z-index', getzIndex('backdrop', this.stack.length))
314
+ .addClass('in');
315
+
316
+ var $spinner = $(this.options.spinner)
317
+ .css('z-index', getzIndex('modal', this.stack.length))
318
+ .appendTo(this.$element)
319
+ .addClass('in');
320
+
321
+ this.$spinner = $(this.createContainer())
322
+ .append($spinner)
323
+ .on('click.modalmanager', $.proxy(this.loading, this));
324
+
325
+ this.isLoading = true;
326
+
327
+ $.support.transition ?
328
+ this.$backdropHandle.one($.support.transition.end, callback) :
329
+ callback();
330
+
331
+ } else if (this.isLoading && this.$backdropHandle) {
332
+ this.$backdropHandle.removeClass('in');
333
+
334
+ var that = this;
335
+ $.support.transition ?
336
+ this.$backdropHandle.one($.support.transition.end, function () { that.removeLoading() }) :
337
+ that.removeLoading();
338
+
339
+ } else if (callback) {
340
+ callback(this.isLoading);
341
+ }
361
342
  }
343
+ };
344
+
345
+ /* PRIVATE METHODS
346
+ * ======================= */
347
+
348
+ // computes and caches the zindexes
349
+ var getzIndex = (function () {
350
+ var zIndexFactor,
351
+ baseIndex = {};
352
+
353
+ return function (type, pos) {
362
354
 
363
- $.fn.modalmanager.defaults = {
364
- backdropLimit: 999,
365
- spinner: '<div class="loading-spinner fade" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>'
355
+ if (typeof zIndexFactor === 'undefined'){
356
+ var $baseModal = $('<div class="modal hide" />').appendTo('body'),
357
+ $baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
358
+
359
+ baseIndex['modal'] = +$baseModal.css('z-index');
360
+ baseIndex['backdrop'] = +$baseBackdrop.css('z-index');
361
+ zIndexFactor = baseIndex['modal'] - baseIndex['backdrop'];
362
+
363
+ $baseModal.remove();
364
+ $baseBackdrop.remove();
365
+ $baseBackdrop = $baseModal = null;
366
+ }
367
+
368
+ return baseIndex[type] + (zIndexFactor * pos);
369
+
370
+ }
371
+ }());
372
+
373
+ // make sure the event target is the modal itself in order to prevent
374
+ // other components such as tabsfrom triggering the modal manager.
375
+ // if Boostsrap namespaced events, this would not be needed.
376
+ function targetIsSelf(callback){
377
+ return function (e) {
378
+ if (this === e.target){
379
+ return callback.apply(this, arguments);
380
+ }
366
381
  }
382
+ }
383
+
384
+
385
+ /* MODAL MANAGER PLUGIN DEFINITION
386
+ * ======================= */
387
+
388
+ $.fn.modalmanager = function (option, args) {
389
+ return this.each(function () {
390
+ var $this = $(this),
391
+ data = $this.data('modalmanager');
392
+
393
+ if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)))
394
+ if (typeof option === 'string') data[option].apply(data, [].concat(args))
395
+ })
396
+ };
397
+
398
+ $.fn.modalmanager.defaults = {
399
+ backdropLimit: 999,
400
+ resize: true,
401
+ spinner: '<div class="loading-spinner fade" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>'
402
+ };
367
403
 
368
- $.fn.modalmanager.Constructor = ModalManager
404
+ $.fn.modalmanager.Constructor = ModalManager
369
405
 
370
- }(jQuery);
406
+ }(jQuery);