• Jump To … +
    affix.js alert.js button.js carousel.js collapse.js dropdown.js modal.js popover.js scrollspy.js tab.js tooltip.js transition.js
  • modal.js

  • ¶
    /* ========================================================================
     * Bootstrap: modal.js v3.0.0
     * http://twbs.github.com/bootstrap/javascript.html#modals
     * ========================================================================
     * Copyright 2012 Twitter, Inc.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     * ======================================================================== */
  • ¶

    Strict Mode is a new feature in ECMAScript 5 that allows to place a program, or a function, in a "strict" operating context. This strict context prevents certain actions from being taken and throws more exceptions.

    +function ($) { "use strict";
  • ¶

    MODAL CLASS DEFINITION

  • ¶
      var Modal = function (element, options) {
        this.options   = options
        this.$element  = $(element)
        this.$backdrop =
        this.isShown   = null
    
        if (this.options.remote) this.$element.load(this.options.remote)
      }
    
      Modal.DEFAULTS = {
          backdrop: true
        , keyboard: true
        , show: true
      }
    
      Modal.prototype.toggle = function (_relatedTarget) {
        return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
      }
    
      Modal.prototype.show = function (_relatedTarget) {
        var that = this
        var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
    
        this.$element.trigger(e)
    
        if (this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = true
    
        this.escape()
    
        this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
    
        this.backdrop(function () {
          var transition = $.support.transition && that.$element.hasClass('fade')
    
          if (!that.$element.parent().length) {
            that.$element.appendTo(document.body) // don't move modals dom position
          }
    
          that.$element.show()
    
          if (transition) {
            that.$element[0].offsetWidth // force reflow
          }
    
          that.$element
            .addClass('in')
            .attr('aria-hidden', false)
    
          that.enforceFocus()
    
          var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
    
          transition ?
            that.$element.find('.modal-dialog') // wait for modal to slide in
              .one($.support.transition.end, function () {
                that.$element.focus().trigger(e)
              })
              .emulateTransitionEnd(300) :
            that.$element.focus().trigger(e)
        })
      }
    
      Modal.prototype.hide = function (e) {
        if (e) e.preventDefault()
    
        e = $.Event('hide.bs.modal')
    
        this.$element.trigger(e)
    
        if (!this.isShown || e.isDefaultPrevented()) return
    
        this.isShown = false
    
        this.escape()
    
        $(document).off('focusin.bs.modal')
    
        this.$element
          .removeClass('in')
          .attr('aria-hidden', true)
          .off('click.dismiss.modal')
    
        $.support.transition && this.$element.hasClass('fade') ?
          this.$element
            .one($.support.transition.end, $.proxy(this.hideModal, this))
            .emulateTransitionEnd(300) :
          this.hideModal()
      }
    
      Modal.prototype.enforceFocus = function () {
        $(document)
          .off('focusin.bs.modal') // guard against infinite focus loop
          .on('focusin.bs.modal', $.proxy(function (e) {
            if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
              this.$element.focus()
            }
          }, this))
      }
    
      Modal.prototype.escape = function () {
        if (this.isShown && this.options.keyboard) {
          this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
            e.which == 27 && this.hide()
          }, this))
        } else if (!this.isShown) {
          this.$element.off('keyup.dismiss.bs.modal')
        }
      }
    
      Modal.prototype.hideModal = function () {
        var that = this
        this.$element.hide()
        this.backdrop(function () {
          that.removeBackdrop()
          that.$element.trigger('hidden.bs.modal')
        })
      }
    
      Modal.prototype.removeBackdrop = function () {
        this.$backdrop && this.$backdrop.remove()
        this.$backdrop = null
      }
    
      Modal.prototype.backdrop = function (callback) {
        var that    = this
        var animate = this.$element.hasClass('fade') ? 'fade' : ''
    
        if (this.isShown && this.options.backdrop) {
          var doAnimate = $.support.transition && animate
    
          this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
            .appendTo(document.body)
    
          this.$element.on('click.dismiss.modal', $.proxy(function (e) {
            if (e.target !== e.currentTarget) return
            this.options.backdrop == 'static'
              ? this.$element[0].focus.call(this.$element[0])
              : this.hide.call(this)
          }, this))
    
          if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
    
          this.$backdrop.addClass('in')
    
          if (!callback) return
    
          doAnimate ?
            this.$backdrop
              .one($.support.transition.end, callback)
              .emulateTransitionEnd(150) :
            callback()
    
        } else if (!this.isShown && this.$backdrop) {
          this.$backdrop.removeClass('in')
    
          $.support.transition && this.$element.hasClass('fade')?
            this.$backdrop
              .one($.support.transition.end, callback)
              .emulateTransitionEnd(150) :
            callback()
    
        } else if (callback) {
          callback()
        }
      }
  • ¶

    MODAL PLUGIN DEFINITION

  • ¶
      var old = $.fn.modal
    
      $.fn.modal = function (option, _relatedTarget) {
        return this.each(function () {
  • ¶

    $this is the modal DOM element.

          var $this   = $(this)
  • ¶

    Bootstrap use $this to stock the Modal object namespaced by bs.modal. So we recover what is currently stocked.

          var data    = $this.data('bs.modal')
  • ¶

    Use extend jQuery function to merge data contained in this objects:

    • {} creates an empty object.
    • Modal.DEFAULTS contains the default parameters of the Modal Plugin.
    • $this.data() provides the data stocked in data-* attributes.
    • option is merged only if it is an object.
          var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  • ¶

    If data is empty we stock in it a new Modal object.

          if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  • ¶

    If option is a string then that means the Modal plugin was call to make an order. Examples :

    • $('#myModal').modal('toggle')
    • $('#myModal').modal('show')
    • $('#myModal').modal('hide')
          if (typeof option == 'string') data[option](_relatedTarget)
          else if (options.show) data.show(_relatedTarget)
        })
      }
    
      $.fn.modal.Constructor = Modal
  • ¶

    MODAL NO CONFLICT

  • ¶
      $.fn.modal.noConflict = function () {
        $.fn.modal = old
        return this
      }
  • ¶

    MODAL DATA-API

  • ¶

    This jQuery selector catches any DOM element that contains data-toggle=modal attribute and attachs a click namespaced event handler function. Read the Event names and namespaces chapter (jquery.com) for more information.

      $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  • ¶

    Contains the DOM element previously selected

        var $this   = $(this)
  • ¶

    The href attribute contains the id of the modal div

        var href    = $this.attr('href')
  • ¶

    $target is a DOM element selected by id provided by the href attribute or the data-target attribute

        var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
        var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  • ¶

    The default action of the event will not be triggered

        e.preventDefault()
    
        $target
          .modal(option, this)
          .one('hide', function () {
            $this.is(':visible') && $this.focus()
          })
      })
  • ¶

    Adds listeners to assign modal-open css class to the body in order to add overflow: hidden and remove the scrollbar or display it only if the content of the modal is too long.

      $(document)
        .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })
        .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
    
    }(window.jQuery);