modal.js 6.5 KB

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