modal.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /* ========================================================================
  2. * Bootstrap: modal.js v3.0.3
  3. * http://getbootstrap.com/javascript/#modals
  4. * ========================================================================
  5. * Copyright 2013 Twitter, Inc.
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * ======================================================================== */
  19. +function ($) { "use strict";
  20. // MODAL CLASS DEFINITION
  21. // ======================
  22. var Modal = function (element, options) {
  23. this.options = options
  24. this.$element = $(element)
  25. this.$backdrop =
  26. this.isShown = null
  27. if (this.options.remote) this.$element.load(this.options.remote)
  28. }
  29. Modal.DEFAULTS = {
  30. backdrop: true
  31. , keyboard: true
  32. , show: true
  33. }
  34. Modal.prototype.toggle = function (_relatedTarget) {
  35. return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
  36. }
  37. Modal.prototype.show = function (_relatedTarget) {
  38. var that = this
  39. var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
  40. this.$element.trigger(e)
  41. if (this.isShown || e.isDefaultPrevented()) return
  42. this.isShown = true
  43. this.escape()
  44. this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  45. this.backdrop(function () {
  46. var transition = $.support.transition && that.$element.hasClass('fade')
  47. if (!that.$element.parent().length) {
  48. that.$element.appendTo(document.body) // don't move modals dom position
  49. }
  50. that.$element.show()
  51. if (transition) {
  52. that.$element[0].offsetWidth // force reflow
  53. }
  54. that.$element
  55. .addClass('in')
  56. .attr('aria-hidden', false)
  57. that.enforceFocus()
  58. var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  59. transition ?
  60. that.$element.find('.modal-dialog') // wait for modal to slide in
  61. .one($.support.transition.end, function () {
  62. that.$element.focus().trigger(e)
  63. })
  64. .emulateTransitionEnd(300) :
  65. that.$element.focus().trigger(e)
  66. })
  67. }
  68. Modal.prototype.hide = function (e) {
  69. if (e) e.preventDefault()
  70. e = $.Event('hide.bs.modal')
  71. this.$element.trigger(e)
  72. if (!this.isShown || e.isDefaultPrevented()) return
  73. this.isShown = false
  74. this.escape()
  75. $(document).off('focusin.bs.modal')
  76. this.$element
  77. .removeClass('in')
  78. .attr('aria-hidden', true)
  79. .off('click.dismiss.modal')
  80. $.support.transition && this.$element.hasClass('fade') ?
  81. this.$element
  82. .one($.support.transition.end, $.proxy(this.hideModal, this))
  83. .emulateTransitionEnd(300) :
  84. this.hideModal()
  85. }
  86. Modal.prototype.enforceFocus = function () {
  87. $(document)
  88. .off('focusin.bs.modal') // guard against infinite focus loop
  89. .on('focusin.bs.modal', $.proxy(function (e) {
  90. if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  91. this.$element.focus()
  92. }
  93. }, this))
  94. }
  95. Modal.prototype.escape = function () {
  96. if (this.isShown && this.options.keyboard) {
  97. this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
  98. e.which == 27 && this.hide()
  99. }, this))
  100. } else if (!this.isShown) {
  101. this.$element.off('keyup.dismiss.bs.modal')
  102. }
  103. }
  104. Modal.prototype.hideModal = function () {
  105. var that = this
  106. this.$element.hide()
  107. this.backdrop(function () {
  108. that.removeBackdrop()
  109. that.$element.trigger('hidden.bs.modal')
  110. })
  111. }
  112. Modal.prototype.removeBackdrop = function () {
  113. this.$backdrop && this.$backdrop.remove()
  114. this.$backdrop = null
  115. }
  116. Modal.prototype.backdrop = function (callback) {
  117. var that = this
  118. var animate = this.$element.hasClass('fade') ? 'fade' : ''
  119. if (this.isShown && this.options.backdrop) {
  120. var doAnimate = $.support.transition && animate
  121. this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
  122. .appendTo(document.body)
  123. this.$element.on('click.dismiss.modal', $.proxy(function (e) {
  124. if (e.target !== e.currentTarget) return
  125. this.options.backdrop == 'static'
  126. ? this.$element[0].focus.call(this.$element[0])
  127. : this.hide.call(this)
  128. }, this))
  129. if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  130. this.$backdrop.addClass('in')
  131. if (!callback) return
  132. doAnimate ?
  133. this.$backdrop
  134. .one($.support.transition.end, callback)
  135. .emulateTransitionEnd(150) :
  136. callback()
  137. } else if (!this.isShown && this.$backdrop) {
  138. this.$backdrop.removeClass('in')
  139. $.support.transition && this.$element.hasClass('fade')?
  140. this.$backdrop
  141. .one($.support.transition.end, callback)
  142. .emulateTransitionEnd(150) :
  143. callback()
  144. } else if (callback) {
  145. callback()
  146. }
  147. }
  148. // MODAL PLUGIN DEFINITION
  149. // =======================
  150. var old = $.fn.modal
  151. $.fn.modal = function (option, _relatedTarget) {
  152. return this.each(function () {
  153. var $this = $(this)
  154. var data = $this.data('bs.modal')
  155. var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  156. if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  157. if (typeof option == 'string') data[option](_relatedTarget)
  158. else if (options.show) data.show(_relatedTarget)
  159. })
  160. }
  161. $.fn.modal.Constructor = Modal
  162. // MODAL NO CONFLICT
  163. // =================
  164. $.fn.modal.noConflict = function () {
  165. $.fn.modal = old
  166. return this
  167. }
  168. // MODAL DATA-API
  169. // ==============
  170. $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  171. var $this = $(this)
  172. var href = $this.attr('href')
  173. var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
  174. var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  175. e.preventDefault()
  176. $target
  177. .modal(option, this)
  178. .one('hide', function () {
  179. $this.is(':visible') && $this.focus()
  180. })
  181. })
  182. $(document)
  183. .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
  184. .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
  185. }(jQuery);