bootstrap_modal_rails 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,176 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ Bootstrap Modal v2.0
2
+ =============
3
+
4
+ See live demo [here](http://jschr.github.com/bootstrap-modal/).
5
+
6
+ Extends Bootstrap's native modals to provide additional functionality. Introduces a **ModalManager** class that operates behind the scenes to handle multiple modals by listening on their events.
7
+
8
+ A single ModalManager is created by default on body and can be accessed through the jQuery plugin interface.
9
+
10
+ $('body').modalmanager('loading');
11
+
12
+ Bootstrap-Modal can be used as a replacement for Bootstrap's Modal class or as a patch to the library.
13
+
14
+ Overview
15
+ -----------
16
+
17
+ + Backwards compatible
18
+ + Responsive
19
+ + Stackable
20
+ + Full width
21
+ + Load content via AJAX
22
+ + Disable background scrolling
23
+
24
+
25
+ Installation
26
+ -----------
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ gem 'bootstrap_modal_rails', '~> 2.0.0'
31
+
32
+ And then execute:
33
+
34
+ $ bundle
35
+
36
+ Or install it yourself as:
37
+
38
+ $ gem install bootstrap_modal_rails
39
+
40
+ Options
41
+ -----------
42
+
43
+ In addition to the standard bootstrap options, you now have access to the following options
44
+
45
+ **Modal**
46
+
47
+ + **width**
48
+ Set the inital width of the modal.
49
+
50
+ + **height**
51
+ Set the inital height of the modal.
52
+
53
+ + **maxHeight**
54
+ Set the max-height of the modal-body.
55
+
56
+ + **loading**
57
+ Toggle the loading state.
58
+
59
+ + **spinner**
60
+ Provide a custom image or animation for the loading spinner.
61
+
62
+ + **consumeTab**
63
+ Used to enable tabindexing for modals with `data-tabindex`. This is set to true by default.
64
+
65
+ + **focusOn**
66
+ The element or selector to set the focus to once the modal is shown.
67
+
68
+ + **attentionAnimation**
69
+ Set the animation used by the `attention` method. Any animation in [animate.css](http://daneden.me/animate/) is supported but only the *shake* animation is included by default.
70
+
71
+ + **modalOverflow**
72
+ Set this property to true for modals with highly dynamic content. This will force the modal to behave as if it is larger than the viewport.
73
+
74
+ + **manager**
75
+ Set the modal's manager. By default this is set to the `GlobalModalManager` and will most likely not need to be overridden.
76
+
77
+ **ModalManager**
78
+
79
+ + **loading**
80
+ Toggle the loading state.
81
+
82
+ + **backdropLimit**
83
+ Limit the amount of backdrops that will appear on the page at the same time.
84
+
85
+ + **spinner**
86
+ Provide a custom image or animation for the loading spinner.
87
+
88
+ Disable Background Scrolling
89
+ -----------
90
+
91
+ If you want to prevent the background page from scrolling (see [demo](http://jschr.github.com/bootstrap-modal/) for example) you must wrap the page contents in a `<div class="page-container">`. For example:
92
+
93
+ <body>
94
+ <div class="page-container">
95
+ <div class="navbar navbar-fixed-top">...</div>
96
+ <div class="container">...</div>
97
+ </div>
98
+ </body>
99
+
100
+ The reason for doing this instead of just simply setting `overflow: hidden` when a modal is open is to avoid having the page shift as a result of the scrollbar appearing/disappearing. This also allows the document to be scrollable when there is a tall modal but only to the height of the modal, not the entire page.
101
+
102
+ Constrain Modal to Window Size
103
+ -----------
104
+
105
+ You can bind the the height of the modal body to the window with something like this:
106
+
107
+ $.fn.modal.defaults.maxHeight = function(){
108
+ // subtract the height of the modal header and footer
109
+ return $(window).height() - 165;
110
+ }
111
+
112
+ **Note:** This will be overwritten by the responsiveness and is only set when the modal is displayed, not when the window is resized.
113
+
114
+ Tab Index for Modal Forms
115
+ -----------
116
+ You can use `data-tabindex` instead of the default `tabindex` to specify the tabindex within a modal.
117
+
118
+ <input type="text" data-tabindex="1" />
119
+ <input type="text" data-tabindex="2" />
120
+
121
+ See the stackable example on the [demo](http://jschr.github.com/bootstrap-modal/) page for an example.
122
+
123
+ Contributing
124
+ -----------
125
+
126
+ 1. Fork it
127
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
128
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
129
+ 4. Push to the branch (`git push origin my-new-feature`)
130
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module BootstrapModalRails
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,8 @@
1
+ require "bootstrap_modal_rails/version"
2
+
3
+ module BootstrapModalRails
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,355 @@
1
+ /* ===========================================================
2
+ * bootstrap-modal.js v2.0
3
+ * ===========================================================
4
+ * Copyright 2012 Jordan Schroter
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ * ========================================================== */
18
+
19
+
20
+ !function ($) {
21
+
22
+ "use strict"; // jshint ;_;
23
+
24
+ /* MODAL CLASS DEFINITION
25
+ * ====================== */
26
+
27
+ var Modal = function (element, options) {
28
+ this.init(element, options);
29
+ }
30
+
31
+ Modal.prototype = {
32
+
33
+ constructor: Modal,
34
+
35
+ init: function (element, options) {
36
+ this.options = options;
37
+
38
+ this.$element = $(element)
39
+ .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this));
40
+
41
+ this.options.remote && this.$element.find('.modal-body').load(this.options.remote);
42
+
43
+ var manager = typeof this.options.manager === 'function' ?
44
+ this.options.manager.call(this) : this.options.manager;
45
+
46
+ manager = manager.appendModal ?
47
+ manager : $(manager).modalmanager().data('modalmanager');
48
+
49
+ manager.appendModal(this);
50
+ },
51
+
52
+ toggle: function () {
53
+ return this[!this.isShown ? 'show' : 'hide']();
54
+ },
55
+
56
+ show: function () {
57
+ var that = this,
58
+ e = $.Event('show');
59
+
60
+ if (this.isShown) return;
61
+
62
+ this.$element.triggerHandler(e);
63
+
64
+ if (e.isDefaultPrevented()) return;
65
+
66
+ if (this.options.width){
67
+ this.$element.css('width', this.options.width);
68
+
69
+ var that = this;
70
+ this.$element.css('margin-left', function () {
71
+ if (/%/ig.test(that.options.width)){
72
+ return -(parseInt(that.options.width) / 2) + '%';
73
+ } else {
74
+ return -($(this).width() / 2) + 'px';
75
+ }
76
+ });
77
+ }
78
+
79
+ var prop = this.options.height ? 'height' : 'max-height';
80
+
81
+ var value = this.options.height || this.options.maxHeight;
82
+
83
+ if (value){
84
+ this.$element.find('.modal-body')
85
+ .css('overflow', 'auto')
86
+ .css(prop, value);
87
+ }
88
+
89
+ this.escape();
90
+
91
+ this.tab();
92
+
93
+ this.options.loading && this.loading();
94
+ },
95
+
96
+ hide: function (e) {
97
+ e && e.preventDefault();
98
+
99
+ e = $.Event('hide');
100
+
101
+ this.$element.triggerHandler(e);
102
+
103
+ if (!this.isShown || e.isDefaultPrevented()) return (this.isShown = false);
104
+
105
+ this.isShown = false;
106
+
107
+ this.escape();
108
+
109
+ this.tab();
110
+
111
+ this.isLoading && this.loading();
112
+
113
+ $(document).off('focusin.modal');
114
+
115
+ this.$element
116
+ .removeClass('in')
117
+ .removeClass('animated')
118
+ .removeClass(this.options.attentionAnimation)
119
+ .removeClass('modal-overflow')
120
+ .attr('aria-hidden', true);
121
+
122
+ $.support.transition && this.$element.hasClass('fade') ?
123
+ this.hideWithTransition() :
124
+ this.hideModal();
125
+ },
126
+
127
+ tab: function () {
128
+ var that = this;
129
+
130
+ if (this.isShown && this.options.consumeTab) {
131
+ this.$element.on('keydown.tabindex.modal', '[data-tabindex]', function (e) {
132
+ if (e.keyCode && e.keyCode == 9){
133
+ var $next = $(this),
134
+ $rollover = $(this);
135
+
136
+ that.$element.find('[data-tabindex]:enabled:not([readonly])').each(function (e) {
137
+ if (!e.shiftKey){
138
+ $next = $next.data('tabindex') < $(this).data('tabindex') ?
139
+ $next = $(this) :
140
+ $rollover = $(this);
141
+ } else {
142
+ $next = $next.data('tabindex') > $(this).data('tabindex') ?
143
+ $next = $(this) :
144
+ $rollover = $(this);
145
+ }
146
+ });
147
+
148
+ $next[0] !== $(this)[0] ?
149
+ $next.focus() : $rollover.focus();
150
+
151
+ e.preventDefault();
152
+
153
+ }
154
+ });
155
+ } else if (!this.isShown) {
156
+ this.$element.off('keydown.tabindex.modal');
157
+ }
158
+ },
159
+
160
+ escape: function () {
161
+ var that = this;
162
+ if (this.isShown && this.options.keyboard) {
163
+ if (!this.$element.attr('tabindex')) this.$element.attr('tabindex', -1);
164
+
165
+ this.$element.on('keyup.dismiss.modal', function (e) {
166
+ e.which == 27 && that.hide();
167
+ });
168
+ } else if (!this.isShown) {
169
+ this.$element.off('keyup.dismiss.modal')
170
+ }
171
+ },
172
+
173
+ hideWithTransition: function () {
174
+ var that = this
175
+ , timeout = setTimeout(function () {
176
+ that.$element.off($.support.transition.end)
177
+ that.hideModal()
178
+ }, 500);
179
+
180
+ this.$element.one($.support.transition.end, function () {
181
+ clearTimeout(timeout)
182
+ that.hideModal()
183
+ });
184
+ },
185
+
186
+ hideModal: function () {
187
+ this.$element
188
+ .hide()
189
+ .triggerHandler('hidden');
190
+
191
+
192
+ var prop = this.options.height ? 'height' : 'max-height';
193
+ var value = this.options.height || this.options.maxHeight;
194
+
195
+ if (value){
196
+ this.$element.find('.modal-body')
197
+ .css('overflow', '')
198
+ .css(prop, '');
199
+ }
200
+
201
+ },
202
+
203
+ removeLoading: function () {
204
+ this.$loading.remove();
205
+ this.$loading = null;
206
+ this.isLoading = false;
207
+ },
208
+
209
+ loading: function (callback) {
210
+ callback = callback || function () {};
211
+
212
+ var animate = this.$element.hasClass('fade') ? 'fade' : '';
213
+
214
+ if (!this.isLoading) {
215
+ var doAnimate = $.support.transition && animate;
216
+
217
+ this.$loading = $('<div class="loading-mask ' + animate + '">')
218
+ .append(this.options.spinner)
219
+ .appendTo(this.$element);
220
+
221
+ if (doAnimate) this.$loading[0].offsetWidth // force reflow
222
+
223
+ this.$loading.addClass('in')
224
+
225
+ this.isLoading = true;
226
+
227
+ doAnimate ?
228
+ this.$loading.one($.support.transition.end, callback) :
229
+ callback();
230
+
231
+ } else if (this.isLoading && this.$loading) {
232
+ this.$loading.removeClass('in');
233
+
234
+ var that = this;
235
+ $.support.transition && this.$element.hasClass('fade')?
236
+ this.$loading.one($.support.transition.end, function () { that.removeLoading() }) :
237
+ that.removeLoading();
238
+
239
+ } else if (callback) {
240
+ callback(this.isLoading);
241
+ }
242
+ },
243
+
244
+ focus: function () {
245
+ var $focusElem = this.$element.find(this.options.focusOn);
246
+
247
+ $focusElem = $focusElem.length ? $focusElem : this.$element;
248
+
249
+ $focusElem.focus();
250
+ },
251
+
252
+ attention: function (){
253
+ // NOTE: transitionEnd with keyframes causes odd behaviour
254
+
255
+ if (this.options.attentionAnimation){
256
+ this.$element
257
+ .removeClass('animated')
258
+ .removeClass(this.options.attentionAnimation);
259
+
260
+ var that = this;
261
+
262
+ setTimeout(function () {
263
+ that.$element
264
+ .addClass('animated')
265
+ .addClass(that.options.attentionAnimation);
266
+ }, 0);
267
+ }
268
+
269
+
270
+ this.focus();
271
+ },
272
+
273
+
274
+ destroy: function () {
275
+ var e = $.Event('destroy');
276
+ this.$element.triggerHandler(e);
277
+ if (e.isDefaultPrevented()) return;
278
+
279
+ this.teardown();
280
+ },
281
+
282
+ teardown: function () {
283
+ if (!this.$parent.length){
284
+ this.$element.remove();
285
+ this.$element = null;
286
+ return;
287
+ }
288
+
289
+ if (this.$parent !== this.$element.parent()){
290
+ this.$element.appendTo(this.$parent);
291
+ }
292
+
293
+ this.$element.off('.modal');
294
+ this.$element.removeData('modal');
295
+ this.$element
296
+ .removeClass('in')
297
+ .attr('aria-hidden', true);
298
+ }
299
+ }
300
+
301
+
302
+ /* MODAL PLUGIN DEFINITION
303
+ * ======================= */
304
+
305
+ $.fn.modal = function (option) {
306
+ return this.each(function () {
307
+ var $this = $(this),
308
+ data = $this.data('modal'),
309
+ options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option);
310
+
311
+ if (!data) $this.data('modal', (data = new Modal(this, options)))
312
+ if (typeof option == 'string') data[option]()
313
+ else if (options.show) data.show()
314
+ })
315
+ }
316
+
317
+ $.fn.modal.defaults = {
318
+ keyboard: true,
319
+ backdrop: true,
320
+ loading: false,
321
+ show: true,
322
+ width: null,
323
+ height: null,
324
+ maxHeight: null,
325
+ modalOverflow: false,
326
+ consumeTab: true,
327
+ focusOn: null,
328
+ attentionAnimation: 'shake',
329
+ manager: 'body',
330
+ spinner: '<div class="loading-spinner" style="width: 200px; margin-left: -100px;"><div class="progress progress-striped active"><div class="bar" style="width: 100%;"></div></div></div>'
331
+ }
332
+
333
+ $.fn.modal.Constructor = Modal
334
+
335
+
336
+ /* MODAL DATA-API
337
+ * ============== */
338
+
339
+ $(function () {
340
+ $(document).off('.modal').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
341
+ var $this = $(this),
342
+ href = $this.attr('href'),
343
+ $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))), //strip for ie7
344
+ option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data());
345
+
346
+ e.preventDefault();
347
+ $target
348
+ .modal(option)
349
+ .one('hide', function () {
350
+ $this.focus();
351
+ })
352
+ });
353
+ });
354
+
355
+ }(window.jQuery);
@@ -0,0 +1,370 @@
1
+ /* ===========================================================
2
+ * bootstrap-modalmanager.js v2.0
3
+ * ===========================================================
4
+ * Copyright 2012 Jordan Schroter.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ * ========================================================== */
18
+
19
+ !function ($) {
20
+
21
+ "use strict"; // jshint ;_;
22
+
23
+ /* MODAL MANAGER CLASS DEFINITION
24
+ * ====================== */
25
+
26
+ var ModalManager = function (element, options) {
27
+ this.init(element, options);
28
+ }
29
+
30
+ ModalManager.prototype = {
31
+
32
+ constructor: ModalManager,
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
+ },
40
+
41
+ createModal: function (element, options) {
42
+ $(element).modal($.extend({ manager: this }, options));
43
+ },
44
+
45
+ appendModal: function (modal) {
46
+ this.stack.push(modal);
47
+
48
+ var that = this;
49
+
50
+ modal.$element.on('show.modalmanager', targetIsSelf(function (e) {
51
+ modal.isShown = true;
52
+
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
+
63
+ modal.$element.appendTo(modal.$container);
64
+
65
+ var modalOverflow = $(window).height() < modal.$element.height() || modal.options.modalOverflow;
66
+
67
+ that.backdrop(modal, function () {
68
+
69
+ modal.$element.show();
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
+ }
76
+
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
+ }
87
+
88
+ transition ?
89
+ modal.$element.one($.support.transition.end, complete) :
90
+ complete();
91
+ });
92
+ }));
93
+
94
+ modal.$element.on('hidden.modalmanager', targetIsSelf(function (e) {
95
+
96
+ that.backdrop(modal);
97
+
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
+ }
105
+
106
+ }));
107
+
108
+ modal.$element.on('destroy.modalmanager', targetIsSelf(function (e) {
109
+ that.removeModal(modal);
110
+ }));
111
+ },
112
+
113
+ destroyModal: function (modal) {
114
+
115
+ modal.destroy();
116
+
117
+ var hasOpenModal = this.hasOpenModal();
118
+
119
+ this.$element.toggleClass('modal-open', hasOpenModal);
120
+
121
+ if (!hasOpenModal){
122
+ this.$element.removeClass('page-overflow');
123
+ }
124
+
125
+ this.removeContainer(modal);
126
+
127
+ this.setFocus();
128
+ },
129
+
130
+ hasOpenModal: function () {
131
+ for (var i = 0; i < this.stack.length; i++){
132
+ if (this.stack[i].isShown) return true;
133
+ }
134
+
135
+ return false;
136
+ },
137
+
138
+ setFocus: function () {
139
+ var topModal;
140
+
141
+ for (var i = 0; i < this.stack.length; i++){
142
+ if (this.stack[i].isShown) topModal = this.stack[i];
143
+ }
144
+
145
+ if (!topModal) return;
146
+
147
+ topModal.focus();
148
+
149
+ },
150
+
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
+ },
156
+
157
+ getModalAt: function (index) {
158
+ return this.stack[index];
159
+ },
160
+
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
+ }
186
+
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
+ }
212
+
213
+ return $container;
214
+
215
+ },
216
+
217
+ backdrop: function (modal, callback) {
218
+ var animate = modal.$element.hasClass('fade') ? 'fade' : '',
219
+ showBackdrop = modal.options.backdrop &&
220
+ this.backdropCount < this.options.backdropLimit;
221
+
222
+ if (modal.isShown && showBackdrop) {
223
+ var doAnimate = $.support.transition && animate && !this.isLoading;
224
+
225
+
226
+ modal.$backdrop = this.createBackdrop(animate);
227
+
228
+ modal.$backdrop.css('z-index', getzIndex( 'backdrop', this.getIndexOfModal(modal) ))
229
+
230
+ if (doAnimate) modal.$backdrop[0].offsetWidth // force reflow
231
+
232
+ modal.$backdrop.addClass('in')
233
+
234
+ this.backdropCount += 1;
235
+
236
+ doAnimate ?
237
+ modal.$backdrop.one($.support.transition.end, callback) :
238
+ callback();
239
+
240
+ } else if (!modal.isShown && modal.$backdrop) {
241
+ modal.$backdrop.removeClass('in');
242
+
243
+ this.backdropCount -= 1;
244
+
245
+ var that = this;
246
+
247
+ $.support.transition && modal.$element.hasClass('fade')?
248
+ modal.$backdrop.one($.support.transition.end, function () { that.removeBackdrop(modal) }) :
249
+ that.removeBackdrop(modal);
250
+
251
+ } else if (callback) {
252
+ callback();
253
+ }
254
+ },
255
+
256
+ removeLoading: function () {
257
+ this.$loading && this.$loading.remove();
258
+ this.$loading = null;
259
+ this.isLoading = false;
260
+ },
261
+
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) {
270
+
271
+ this.$loading = this.createBackdrop('fade');
272
+
273
+ this.$loading[0].offsetWidth // force reflow
274
+
275
+ this.$loading
276
+ .css('z-index', getzIndex('backdrop', this.stack.length))
277
+ .addClass('in');
278
+
279
+ var $spinner = $(this.options.spinner)
280
+ .css('z-index', getzIndex('modal', this.stack.length))
281
+ .appendTo(this.$element)
282
+ .addClass('in');
283
+
284
+ this.$spinner = $(this.createContainer())
285
+ .append($spinner)
286
+ .on('click.modalmanager', $.proxy(this.loading, this));
287
+
288
+ this.isLoading = true;
289
+
290
+ $.support.transition ?
291
+ this.$loading.one($.support.transition.end, callback) :
292
+ callback();
293
+
294
+ } else if (this.isLoading && this.$loading) {
295
+ this.$loading.removeClass('in');
296
+
297
+ if (this.$spinner) this.$spinner.remove();
298
+
299
+ var that = this;
300
+ $.support.transition ?
301
+ this.$loading.one($.support.transition.end, function () { that.removeLoading() }) :
302
+ that.removeLoading();
303
+
304
+ } else if (callback) {
305
+ callback(this.isLoading);
306
+ }
307
+ }
308
+ }
309
+
310
+ /* PRIVATE METHODS
311
+ * ======================= */
312
+
313
+ // computes and caches the zindexes
314
+ var getzIndex = (function () {
315
+ var zIndexFactor,
316
+ baseIndex = {};
317
+
318
+ return function (type, pos) {
319
+
320
+ if (typeof zIndexFactor === 'undefined'){
321
+ var $baseModal = $('<div class="modal hide" />').appendTo('body'),
322
+ $baseBackdrop = $('<div class="modal-backdrop hide" />').appendTo('body');
323
+
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
+ }
332
+
333
+ return baseIndex[type] + (zIndexFactor * pos);
334
+
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
+ }
348
+
349
+
350
+ /* MODAL MANAGER PLUGIN DEFINITION
351
+ * ======================= */
352
+
353
+ $.fn.modalmanager = function (option) {
354
+ return this.each(function () {
355
+ var $this = $(this),
356
+ data = $this.data('modalmanager');
357
+
358
+ if (!data) $this.data('modalmanager', (data = new ModalManager(this, option)))
359
+ if (typeof option === 'string') data[option]()
360
+ })
361
+ }
362
+
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>'
366
+ }
367
+
368
+ $.fn.modalmanager.Constructor = ModalManager
369
+
370
+ }(jQuery);
@@ -0,0 +1,2 @@
1
+ //= require ./bootstrap-modal.js
2
+ //= require ./bootstrap-modalmanager.js
@@ -0,0 +1,215 @@
1
+ /*!
2
+ * Bootstrap Modal
3
+ *
4
+ * Copyright Jordan Schroter
5
+ * Licensed under the Apache License v2.0
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ */
9
+
10
+ .modal-open {
11
+ position: relative; /* safari */
12
+ overflow: hidden;
13
+ }
14
+
15
+
16
+ /* add a scroll bar to stop page from jerking around */
17
+ .modal-open.page-overflow .page-container,
18
+ .modal-open.page-overflow .page-container .navbar-fixed-top,
19
+ .modal-open.page-overflow .page-container .navbar-fixed-bottom,
20
+ .modal-open.page-overflow .modal-scrollable {
21
+ overflow-y: scroll;
22
+ }
23
+
24
+ @media (max-width: 979px) {
25
+ .modal-open.page-overflow .page-container .navbar-fixed-top,
26
+ .modal-open.page-overflow .page-container .navbar-fixed-bottom {
27
+ overflow-y: visible;
28
+ }
29
+ }
30
+
31
+
32
+ .modal-scrollable {
33
+ position: fixed;
34
+ top: 0;
35
+ bottom: 0;
36
+ left: 0;
37
+ right: 0;
38
+ overflow: auto;
39
+ }
40
+
41
+ .modal {
42
+ outline: none;
43
+ position: absolute;
44
+ margin-top: 0;
45
+ top: 50%;
46
+ overflow: visible; /* allow content to popup out (i.e tooltips) */
47
+ }
48
+
49
+ .modal.fade {
50
+ top: -100%;
51
+ -webkit-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
52
+ -moz-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
53
+ -o-transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
54
+ transition: opacity 0.3s linear, top 0.3s ease-out, bottom 0.3s ease-out, margin-top 0.3s ease-out;
55
+ }
56
+
57
+ .modal.fade.in {
58
+ top: 50%;
59
+ }
60
+
61
+ .modal-body {
62
+ max-height: none;
63
+ overflow: visible;
64
+ }
65
+
66
+ .modal.modal-absolute {
67
+ position: absolute;
68
+ z-index: 950;
69
+ }
70
+
71
+ .modal .loading-mask {
72
+ position: absolute;
73
+ top: 0;
74
+ bottom: 0;
75
+ left: 0;
76
+ right: 0;
77
+ background: #fff;
78
+ border-radius: 6px;
79
+ }
80
+
81
+ .modal-backdrop.modal-absolute{
82
+ position: absolute;
83
+ z-index: 940;
84
+ }
85
+
86
+ .modal-backdrop,
87
+ .modal-backdrop.fade.in{
88
+ opacity: 0.7;
89
+ filter: alpha(opacity=70);
90
+ background: #fff;
91
+ }
92
+
93
+ .modal.container {
94
+ width: 940px;
95
+ margin-left: -470px;
96
+ }
97
+
98
+ /* Modal Overflow */
99
+
100
+ .modal-overflow.modal {
101
+ top: 1%;
102
+ }
103
+
104
+ .modal-overflow.modal.fade {
105
+ top: -100%;
106
+ }
107
+
108
+ .modal-overflow.modal.fade.in {
109
+ top: 1%;
110
+ }
111
+
112
+ .modal-overflow .modal-body {
113
+ overflow: auto;
114
+ -webkit-overflow-scrolling: touch;
115
+ }
116
+
117
+ /* Responsive */
118
+
119
+ @media (min-width: 1200px) {
120
+ .modal.container {
121
+ width: 1170px;
122
+ margin-left: -585px;
123
+ }
124
+ }
125
+
126
+ @media (max-width: 979px) {
127
+ .modal,
128
+ .modal.container,
129
+ .modal.modal-overflow {
130
+ top: 1%;
131
+ right: 1%;
132
+ left: 1%;
133
+ bottom: auto;
134
+ width: auto !important;
135
+ height: auto !important;
136
+ margin: 0 !important;
137
+ padding: 0 !important;
138
+ }
139
+
140
+ .modal.fade.in,
141
+ .modal.container.fade.in,
142
+ .modal.modal-overflow.fade.in {
143
+ top: 1%;
144
+ bottom: auto;
145
+ }
146
+
147
+ .modal-body,
148
+ .modal-overflow .modal-body {
149
+ position: static;
150
+ margin: 0;
151
+ height: auto !important;
152
+ max-height: none !important;
153
+ overflow: visible !important;
154
+ }
155
+
156
+ .modal-footer,
157
+ .modal-overflow .modal-footer {
158
+ position: static;
159
+ }
160
+ }
161
+
162
+ .loading-spinner {
163
+ position: absolute;
164
+ top: 50%;
165
+ left: 50%;
166
+ margin: -12px 0 0 -12px;
167
+ }
168
+
169
+ /*
170
+ Animate.css - http://daneden.me/animate
171
+ Licensed under the ☺ license (http://licence.visualidiot.com/)
172
+
173
+ Copyright (c) 2012 Dan Eden*/
174
+
175
+ .animated {
176
+ -webkit-animation-duration: 1s;
177
+ -moz-animation-duration: 1s;
178
+ -o-animation-duration: 1s;
179
+ animation-duration: 1s;
180
+ -webkit-animation-fill-mode: both;
181
+ -moz-animation-fill-mode: both;
182
+ -o-animation-fill-mode: both;
183
+ animation-fill-mode: both;
184
+ }
185
+
186
+ @-webkit-keyframes shake {
187
+ 0%, 100% {-webkit-transform: translateX(0);}
188
+ 10%, 30%, 50%, 70%, 90% {-webkit-transform: translateX(-10px);}
189
+ 20%, 40%, 60%, 80% {-webkit-transform: translateX(10px);}
190
+ }
191
+
192
+ @-moz-keyframes shake {
193
+ 0%, 100% {-moz-transform: translateX(0);}
194
+ 10%, 30%, 50%, 70%, 90% {-moz-transform: translateX(-10px);}
195
+ 20%, 40%, 60%, 80% {-moz-transform: translateX(10px);}
196
+ }
197
+
198
+ @-o-keyframes shake {
199
+ 0%, 100% {-o-transform: translateX(0);}
200
+ 10%, 30%, 50%, 70%, 90% {-o-transform: translateX(-10px);}
201
+ 20%, 40%, 60%, 80% {-o-transform: translateX(10px);}
202
+ }
203
+
204
+ @keyframes shake {
205
+ 0%, 100% {transform: translateX(0);}
206
+ 10%, 30%, 50%, 70%, 90% {transform: translateX(-10px);}
207
+ 20%, 40%, 60%, 80% {transform: translateX(10px);}
208
+ }
209
+
210
+ .shake {
211
+ -webkit-animation-name: shake;
212
+ -moz-animation-name: shake;
213
+ -o-animation-name: shake;
214
+ animation-name: shake;
215
+ }
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bootstrap_modal_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris McKnight
9
+ - Jordan Schroter
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-12-12 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3.1'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '3.1'
31
+ description: Gem to include bootstrap-modal extension in Rails
32
+ email:
33
+ - cmcknight@immense.net
34
+ - jschr
35
+ executables: []
36
+ extensions: []
37
+ extra_rdoc_files: []
38
+ files:
39
+ - lib/bootstrap_modal_rails/version.rb
40
+ - lib/bootstrap_modal_rails.rb
41
+ - vendor/assets/images/ajax-loader.gif
42
+ - vendor/assets/javascripts/bootstrap_modal_rails/bootstrap-modal.js
43
+ - vendor/assets/javascripts/bootstrap_modal_rails/bootstrap-modalmanager.js
44
+ - vendor/assets/javascripts/bootstrap_modal_rails/index.js
45
+ - vendor/assets/stylesheets/bootstrap_modal_rails/bootstrap-modal.css
46
+ - LICENSE
47
+ - Rakefile
48
+ - README.md
49
+ homepage: http://jschr.github.com/bootstrap-modal/
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ segments:
62
+ - 0
63
+ hash: -1316270724695717750
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ segments:
71
+ - 0
72
+ hash: -1316270724695717750
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 1.8.23
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Extends the default Bootstrap Modal class. Responsive, stackable, ajax and
79
+ more.
80
+ test_files: []