1 /* ===========================================================
\r
2 * bootstrap-modal.js v2.2.5
\r
3 * ===========================================================
\r
4 * Copyright 2012 Jordan Schroter
\r
6 * Licensed under the Apache License, Version 2.0 (the "License");
\r
7 * you may not use this file except in compliance with the License.
\r
8 * You may obtain a copy of the License at
\r
10 * http://www.apache.org/licenses/LICENSE-2.0
\r
12 * Unless required by applicable law or agreed to in writing, software
\r
13 * distributed under the License is distributed on an "AS IS" BASIS,
\r
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
15 * See the License for the specific language governing permissions and
\r
16 * limitations under the License.
\r
17 * ========================================================== */
\r
22 "use strict"; // jshint ;_;
\r
24 /* MODAL CLASS DEFINITION
\r
25 * ====================== */
\r
27 var Modal = function (element, options) {
\r
28 this.init(element, options);
\r
35 init: function (element, options) {
\r
38 this.options = options;
\r
40 this.$element = $(element)
\r
41 .delegate('[data-dismiss="modal"]', 'click.dismiss.modal', $.proxy(this.hide, this));
\r
43 this.options.remote && this.$element.find('.modal-body').load(this.options.remote, function () {
\r
44 var e = $.Event('loaded');
\r
45 that.$element.trigger(e);
\r
48 var manager = typeof this.options.manager === 'function' ?
\r
49 this.options.manager.call(this) : this.options.manager;
\r
51 manager = manager.appendModal ?
\r
52 manager : $(manager).modalmanager().data('modalmanager');
\r
54 manager.appendModal(this);
\r
57 toggle: function () {
\r
58 return this[!this.isShown ? 'show' : 'hide']();
\r
62 var e = $.Event('show');
\r
64 if (this.isShown) return;
\r
66 this.$element.trigger(e);
\r
68 if (e.isDefaultPrevented()) return;
\r
74 this.options.loading && this.loading();
\r
77 hide: function (e) {
\r
78 e && e.preventDefault();
\r
80 e = $.Event('hide');
\r
82 this.$element.trigger(e);
\r
84 if (!this.isShown || e.isDefaultPrevented()) return;
\r
86 this.isShown = false;
\r
92 this.isLoading && this.loading();
\r
94 $(document).off('focusin.modal');
\r
98 .removeClass('animated')
\r
99 .removeClass(this.options.attentionAnimation)
\r
100 .removeClass('modal-overflow')
\r
101 .attr('aria-hidden', true);
\r
103 $.support.transition && this.$element.hasClass('fade') ?
\r
104 this.hideWithTransition() :
\r
108 layout: function () {
\r
109 var prop = this.options.height ? 'height' : 'max-height',
\r
110 value = this.options.height || this.options.maxHeight;
\r
112 if (this.options.width){
\r
113 this.$element.css('width', this.options.width);
\r
116 this.$element.css('margin-left', function () {
\r
117 if (/%/ig.test(that.options.width)){
\r
118 return -(parseInt(that.options.width) / 2) + '%';
\r
120 return -($(this).width() / 2) + 'px';
\r
124 this.$element.css('width', '');
\r
125 this.$element.css('margin-left', '');
\r
128 this.$element.find('.modal-body')
\r
129 .css('overflow', '')
\r
133 this.$element.find('.modal-body')
\r
134 .css('overflow', 'auto')
\r
138 var modalOverflow = $(window).height() - 10 < this.$element.height();
\r
140 if (modalOverflow || this.options.modalOverflow) {
\r
142 .css('margin-top', 0)
\r
143 .addClass('modal-overflow');
\r
146 .css('margin-top', 0 - this.$element.height() / 2)
\r
147 .removeClass('modal-overflow');
\r
154 if (this.isShown && this.options.consumeTab) {
\r
155 this.$element.on('keydown.tabindex.modal', '[data-tabindex]', function (e) {
\r
156 if (e.keyCode && e.keyCode == 9){
\r
158 tabindex = Number($(this).data('tabindex'));
\r
160 that.$element.find('[data-tabindex]:enabled:visible:not([readonly])').each(function (ev) {
\r
161 elements.push(Number($(this).data('tabindex')));
\r
163 elements.sort(function(a,b){return a-b});
\r
165 var arrayPos = $.inArray(tabindex, elements);
\r
167 arrayPos < elements.length-1 ?
\r
168 that.$element.find('[data-tabindex='+elements[arrayPos+1]+']').focus() :
\r
169 that.$element.find('[data-tabindex='+elements[0]+']').focus();
\r
172 that.$element.find('[data-tabindex='+elements[elements.length-1]+']').focus() :
\r
173 that.$element.find('[data-tabindex='+elements[arrayPos-1]+']').focus();
\r
176 e.preventDefault();
\r
179 } else if (!this.isShown) {
\r
180 this.$element.off('keydown.tabindex.modal');
\r
184 escape: function () {
\r
186 if (this.isShown && this.options.keyboard) {
\r
187 if (!this.$element.attr('tabindex')) this.$element.attr('tabindex', -1);
\r
189 this.$element.on('keyup.dismiss.modal', function (e) {
\r
190 e.which == 27 && that.hide();
\r
192 } else if (!this.isShown) {
\r
193 this.$element.off('keyup.dismiss.modal')
\r
197 hideWithTransition: function () {
\r
199 , timeout = setTimeout(function () {
\r
200 that.$element.off($.support.transition.end);
\r
204 this.$element.one($.support.transition.end, function () {
\r
205 clearTimeout(timeout);
\r
210 hideModal: function () {
\r
211 var prop = this.options.height ? 'height' : 'max-height';
\r
212 var value = this.options.height || this.options.maxHeight;
\r
215 this.$element.find('.modal-body')
\r
216 .css('overflow', '')
\r
222 .trigger('hidden');
\r
225 removeLoading: function () {
\r
226 this.$loading.remove();
\r
227 this.$loading = null;
\r
228 this.isLoading = false;
\r
231 loading: function (callback) {
\r
232 callback = callback || function () {};
\r
234 var animate = this.$element.hasClass('fade') ? 'fade' : '';
\r
236 if (!this.isLoading) {
\r
237 var doAnimate = $.support.transition && animate;
\r
239 this.$loading = $('<div class="loading-mask ' + animate + '">')
\r
240 .append(this.options.spinner)
\r
241 .appendTo(this.$element);
\r
243 if (doAnimate) this.$loading[0].offsetWidth; // force reflow
\r
245 this.$loading.addClass('in');
\r
247 this.isLoading = true;
\r
250 this.$loading.one($.support.transition.end, callback) :
\r
253 } else if (this.isLoading && this.$loading) {
\r
254 this.$loading.removeClass('in');
\r
257 $.support.transition && this.$element.hasClass('fade')?
\r
258 this.$loading.one($.support.transition.end, function () { that.removeLoading() }) :
\r
259 that.removeLoading();
\r
261 } else if (callback) {
\r
262 callback(this.isLoading);
\r
266 focus: function () {
\r
267 var $focusElem = this.$element.find(this.options.focusOn);
\r
269 $focusElem = $focusElem.length ? $focusElem : this.$element;
\r
271 $focusElem.focus();
\r
274 attention: function (){
\r
275 // NOTE: transitionEnd with keyframes causes odd behaviour
\r
277 if (this.options.attentionAnimation){
\r
279 .removeClass('animated')
\r
280 .removeClass(this.options.attentionAnimation);
\r
284 setTimeout(function () {
\r
286 .addClass('animated')
\r
287 .addClass(that.options.attentionAnimation);
\r
296 destroy: function () {
\r
297 var e = $.Event('destroy');
\r
299 this.$element.trigger(e);
\r
301 if (e.isDefaultPrevented()) return;
\r
305 .removeData('modal')
\r
307 .attr('aria-hidden', true);
\r
309 if (this.$parent !== this.$element.parent()) {
\r
310 this.$element.appendTo(this.$parent);
\r
311 } else if (!this.$parent.length) {
\r
312 // modal is not part of the DOM so remove it.
\r
313 this.$element.remove();
\r
314 this.$element = null;
\r
317 this.$element.trigger('destroyed');
\r
322 /* MODAL PLUGIN DEFINITION
\r
323 * ======================= */
\r
325 $.fn.modal = function (option, args) {
\r
326 return this.each(function () {
\r
327 var $this = $(this),
\r
328 data = $this.data('modal'),
\r
329 options = $.extend({}, $.fn.modal.defaults, $this.data(), typeof option == 'object' && option);
\r
331 if (!data) $this.data('modal', (data = new Modal(this, options)));
\r
332 if (typeof option == 'string') data[option].apply(data, [].concat(args));
\r
333 else if (options.show) data.show()
\r
337 $.fn.modal.defaults = {
\r
345 modalOverflow: false,
\r
350 attentionAnimation: 'shake',
\r
352 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>',
\r
353 backdropTemplate: '<div class="modal-backdrop" />'
\r
356 $.fn.modal.Constructor = Modal;
\r
360 * ============== */
\r
363 $(document).off('click.modal').on('click.modal.data-api', '[data-toggle="modal"]', function ( e ) {
\r
364 var $this = $(this),
\r
365 href = $this.attr('href'),
\r
366 $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))), //strip for ie7
\r
367 option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data());
\r
369 e.preventDefault();
\r
372 .one('hide', function () {
\r