1 /* ========================================================================
2 * Bootstrap: modal.js v3.3.2
3 * http://getbootstrap.com/javascript/#modals
4 * ========================================================================
5 * Copyright 2011-2015 Twitter, Inc.
6 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7 * ======================================================================== */
13 // MODAL CLASS DEFINITION
14 // ======================
16 var Modal = function (element
, options
) {
17 this.options
= options
18 this.$body
= $(document
.body
)
19 this.$element
= $(element
)
22 this.scrollbarWidth
= 0
24 if (this.options
.remote
) {
26 .find('.modal-content')
27 .load(this.options
.remote
, $.proxy(function () {
28 this.$element
.trigger('loaded.bs.modal')
33 Modal
.VERSION
= '3.3.2'
35 Modal
.TRANSITION_DURATION
= 300
36 Modal
.BACKDROP_TRANSITION_DURATION
= 150
44 Modal
.prototype.toggle = function (_relatedTarget
) {
45 return this.isShown
? this.hide() : this.show(_relatedTarget
)
48 Modal
.prototype.show = function (_relatedTarget
) {
50 var e
= $.Event('show.bs.modal', { relatedTarget
: _relatedTarget
})
52 this.$element
.trigger(e
)
54 if (this.isShown
|| e
.isDefaultPrevented()) return
60 this.$body
.addClass('modal-open')
65 this.$element
.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide
, this))
67 this.backdrop(function () {
68 var transition
= $.support
.transition
&& that
.$element
.hasClass('fade')
70 if (!that
.$element
.parent().length
) {
71 that
.$element
.appendTo(that
.$body
) // don't move modals dom position
78 if (that
.options
.backdrop
) that
.adjustBackdrop()
82 that
.$element
[0].offsetWidth
// force reflow
87 .attr('aria-hidden', false)
91 var e
= $.Event('shown.bs.modal', { relatedTarget
: _relatedTarget
})
94 that
.$element
.find('.modal-dialog') // wait for modal to slide in
95 .one('bsTransitionEnd', function () {
96 that
.$element
.trigger('focus').trigger(e
)
98 .emulateTransitionEnd(Modal
.TRANSITION_DURATION
) :
99 that
.$element
.trigger('focus').trigger(e
)
103 Modal
.prototype.hide = function (e
) {
104 if (e
) e
.preventDefault()
106 e
= $.Event('hide.bs.modal')
108 this.$element
.trigger(e
)
110 if (!this.isShown
|| e
.isDefaultPrevented()) return
117 $(document
).off('focusin.bs.modal')
121 .attr('aria-hidden', true)
122 .off('click.dismiss.bs.modal')
124 $.support
.transition
&& this.$element
.hasClass('fade') ?
126 .one('bsTransitionEnd', $.proxy(this.hideModal
, this))
127 .emulateTransitionEnd(Modal
.TRANSITION_DURATION
) :
131 Modal
.prototype.enforceFocus = function () {
133 .off('focusin.bs.modal') // guard against infinite focus loop
134 .on('focusin.bs.modal', $.proxy(function (e
) {
135 if (this.$element
[0] !== e
.target
&& !this.$element
.has(e
.target
).length
) {
136 this.$element
.trigger('focus')
141 Modal
.prototype.escape = function () {
142 if (this.isShown
&& this.options
.keyboard
) {
143 this.$element
.on('keydown.dismiss.bs.modal', $.proxy(function (e
) {
144 e
.which
== 27 && this.hide()
146 } else if (!this.isShown
) {
147 this.$element
.off('keydown.dismiss.bs.modal')
151 Modal
.prototype.resize = function () {
153 $(window
).on('resize.bs.modal', $.proxy(this.handleUpdate
, this))
155 $(window
).off('resize.bs.modal')
159 Modal
.prototype.hideModal = function () {
162 this.backdrop(function () {
163 that
.$body
.removeClass('modal-open')
164 that
.resetAdjustments()
165 that
.resetScrollbar()
166 that
.$element
.trigger('hidden.bs.modal')
170 Modal
.prototype.removeBackdrop = function () {
171 this.$backdrop
&& this.$backdrop
.remove()
172 this.$backdrop
= null
175 Modal
.prototype.backdrop = function (callback
) {
177 var animate
= this.$element
.hasClass('fade') ? 'fade' : ''
179 if (this.isShown
&& this.options
.backdrop
) {
180 var doAnimate
= $.support
.transition
&& animate
182 this.$backdrop
= $('<div class="modal-backdrop ' + animate
+ '" />')
183 .prependTo(this.$element
)
184 .on('click.dismiss.bs.modal', $.proxy(function (e
) {
185 if (e
.target
!== e
.currentTarget
) return
186 this.options
.backdrop
== 'static'
187 ? this.$element
[0].focus
.call(this.$element
[0])
188 : this.hide
.call(this)
191 if (doAnimate
) this.$backdrop
[0].offsetWidth
// force reflow
193 this.$backdrop
.addClass('in')
195 if (!callback
) return
199 .one('bsTransitionEnd', callback
)
200 .emulateTransitionEnd(Modal
.BACKDROP_TRANSITION_DURATION
) :
203 } else if (!this.isShown
&& this.$backdrop
) {
204 this.$backdrop
.removeClass('in')
206 var callbackRemove = function () {
207 that
.removeBackdrop()
208 callback
&& callback()
210 $.support
.transition
&& this.$element
.hasClass('fade') ?
212 .one('bsTransitionEnd', callbackRemove
)
213 .emulateTransitionEnd(Modal
.BACKDROP_TRANSITION_DURATION
) :
216 } else if (callback
) {
221 // these following methods are used to handle overflowing modals
223 Modal
.prototype.handleUpdate = function () {
224 if (this.options
.backdrop
) this.adjustBackdrop()
228 Modal
.prototype.adjustBackdrop = function () {
231 .css('height', this.$element
[0].scrollHeight
)
234 Modal
.prototype.adjustDialog = function () {
235 var modalIsOverflowing
= this.$element
[0].scrollHeight
> document
.documentElement
.clientHeight
238 paddingLeft
: !this.bodyIsOverflowing
&& modalIsOverflowing
? this.scrollbarWidth
: '',
239 paddingRight
: this.bodyIsOverflowing
&& !modalIsOverflowing
? this.scrollbarWidth
: ''
243 Modal
.prototype.resetAdjustments = function () {
250 Modal
.prototype.checkScrollbar = function () {
251 this.bodyIsOverflowing
= document
.body
.scrollHeight
> document
.documentElement
.clientHeight
252 this.scrollbarWidth
= this.measureScrollbar()
255 Modal
.prototype.setScrollbar = function () {
256 var bodyPad
= parseInt((this.$body
.css('padding-right') || 0), 10)
257 if (this.bodyIsOverflowing
) this.$body
.css('padding-right', bodyPad
+ this.scrollbarWidth
)
260 Modal
.prototype.resetScrollbar = function () {
261 this.$body
.css('padding-right', '')
264 Modal
.prototype.measureScrollbar = function () { // thx walsh
265 var scrollDiv
= document
.createElement('div')
266 scrollDiv
.className
= 'modal-scrollbar-measure'
267 this.$body
.append(scrollDiv
)
268 var scrollbarWidth
= scrollDiv
.offsetWidth
- scrollDiv
.clientWidth
269 this.$body
[0].removeChild(scrollDiv
)
270 return scrollbarWidth
274 // MODAL PLUGIN DEFINITION
275 // =======================
277 function Plugin(option
, _relatedTarget
) {
278 return this.each(function () {
280 var data
= $this.data('bs.modal')
281 var options
= $.extend({}, Modal
.DEFAULTS
, $this.data(), typeof option
== 'object' && option
)
283 if (!data
) $this.data('bs.modal', (data
= new Modal(this, options
)))
284 if (typeof option
== 'string') data
[option
](_relatedTarget
)
285 else if (options
.show
) data
.show(_relatedTarget
)
292 $.fn
.modal
.Constructor
= Modal
298 $.fn
.modal
.noConflict = function () {
307 $(document
).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e
) {
309 var href
= $this.attr('href')
310 var $target
= $($this.attr('data-target') || (href
&& href
.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
311 var option
= $target
.data('bs.modal') ? 'toggle' : $.extend({ remote
: !/#/.test(href
) && href
}, $target
.data(), $this.data())
313 if ($this.is('a')) e
.preventDefault()
315 $target
.one('show.bs.modal', function (showEvent
) {
316 if (showEvent
.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
317 $target
.one('hidden.bs.modal', function () {
318 $this.is(':visible') && $this.trigger('focus')
321 Plugin
.call($target
, option
, this)