github.com/apremalal/vamps-core@v1.0.1-0.20161221121535-d430b56ec174/server/webapps/app/base/plugins/bootstrap/js/bootstrap.js (about)

     1  /*!
     2   * Bootstrap v3.3.2 (http://getbootstrap.com)
     3   * Copyright 2011-2015 Twitter, Inc.
     4   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
     5   */
     6  
     7  if (typeof jQuery === 'undefined') {
     8    throw new Error('Bootstrap\'s JavaScript requires jQuery')
     9  }
    10  
    11  +function ($) {
    12    'use strict';
    13    var version = $.fn.jquery.split(' ')[0].split('.')
    14    if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {
    15      throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher')
    16    }
    17  }(jQuery);
    18  
    19  /* ========================================================================
    20   * Bootstrap: transition.js v3.3.2
    21   * http://getbootstrap.com/javascript/#transitions
    22   * ========================================================================
    23   * Copyright 2011-2015 Twitter, Inc.
    24   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
    25   * ======================================================================== */
    26  
    27  
    28  +function ($) {
    29    'use strict';
    30  
    31    // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
    32    // ============================================================
    33  
    34    function transitionEnd() {
    35      var el = document.createElement('bootstrap')
    36  
    37      var transEndEventNames = {
    38        WebkitTransition : 'webkitTransitionEnd',
    39        MozTransition    : 'transitionend',
    40        OTransition      : 'oTransitionEnd otransitionend',
    41        transition       : 'transitionend'
    42      }
    43  
    44      for (var name in transEndEventNames) {
    45        if (el.style[name] !== undefined) {
    46          return { end: transEndEventNames[name] }
    47        }
    48      }
    49  
    50      return false // explicit for ie8 (  ._.)
    51    }
    52  
    53    // http://blog.alexmaccaw.com/css-transitions
    54    $.fn.emulateTransitionEnd = function (duration) {
    55      var called = false
    56      var $el = this
    57      $(this).one('bsTransitionEnd', function () { called = true })
    58      var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    59      setTimeout(callback, duration)
    60      return this
    61    }
    62  
    63    $(function () {
    64      $.support.transition = transitionEnd()
    65  
    66      if (!$.support.transition) return
    67  
    68      $.event.special.bsTransitionEnd = {
    69        bindType: $.support.transition.end,
    70        delegateType: $.support.transition.end,
    71        handle: function (e) {
    72          if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
    73        }
    74      }
    75    })
    76  
    77  }(jQuery);
    78  
    79  /* ========================================================================
    80   * Bootstrap: alert.js v3.3.2
    81   * http://getbootstrap.com/javascript/#alerts
    82   * ========================================================================
    83   * Copyright 2011-2015 Twitter, Inc.
    84   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
    85   * ======================================================================== */
    86  
    87  
    88  +function ($) {
    89    'use strict';
    90  
    91    // ALERT CLASS DEFINITION
    92    // ======================
    93  
    94    var dismiss = '[data-dismiss="alert"]'
    95    var Alert   = function (el) {
    96      $(el).on('click', dismiss, this.close)
    97    }
    98  
    99    Alert.VERSION = '3.3.2'
   100  
   101    Alert.TRANSITION_DURATION = 150
   102  
   103    Alert.prototype.close = function (e) {
   104      var $this    = $(this)
   105      var selector = $this.attr('data-target')
   106  
   107      if (!selector) {
   108        selector = $this.attr('href')
   109        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
   110      }
   111  
   112      var $parent = $(selector)
   113  
   114      if (e) e.preventDefault()
   115  
   116      if (!$parent.length) {
   117        $parent = $this.closest('.alert')
   118      }
   119  
   120      $parent.trigger(e = $.Event('close.bs.alert'))
   121  
   122      if (e.isDefaultPrevented()) return
   123  
   124      $parent.removeClass('in')
   125  
   126      function removeElement() {
   127        // detach from parent, fire event then clean up data
   128        $parent.detach().trigger('closed.bs.alert').remove()
   129      }
   130  
   131      $.support.transition && $parent.hasClass('fade') ?
   132        $parent
   133          .one('bsTransitionEnd', removeElement)
   134          .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
   135        removeElement()
   136    }
   137  
   138  
   139    // ALERT PLUGIN DEFINITION
   140    // =======================
   141  
   142    function Plugin(option) {
   143      return this.each(function () {
   144        var $this = $(this)
   145        var data  = $this.data('bs.alert')
   146  
   147        if (!data) $this.data('bs.alert', (data = new Alert(this)))
   148        if (typeof option == 'string') data[option].call($this)
   149      })
   150    }
   151  
   152    var old = $.fn.alert
   153  
   154    $.fn.alert             = Plugin
   155    $.fn.alert.Constructor = Alert
   156  
   157  
   158    // ALERT NO CONFLICT
   159    // =================
   160  
   161    $.fn.alert.noConflict = function () {
   162      $.fn.alert = old
   163      return this
   164    }
   165  
   166  
   167    // ALERT DATA-API
   168    // ==============
   169  
   170    $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
   171  
   172  }(jQuery);
   173  
   174  /* ========================================================================
   175   * Bootstrap: button.js v3.3.2
   176   * http://getbootstrap.com/javascript/#buttons
   177   * ========================================================================
   178   * Copyright 2011-2015 Twitter, Inc.
   179   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   180   * ======================================================================== */
   181  
   182  
   183  +function ($) {
   184    'use strict';
   185  
   186    // BUTTON PUBLIC CLASS DEFINITION
   187    // ==============================
   188  
   189    var Button = function (element, options) {
   190      this.$element  = $(element)
   191      this.options   = $.extend({}, Button.DEFAULTS, options)
   192      this.isLoading = false
   193    }
   194  
   195    Button.VERSION  = '3.3.2'
   196  
   197    Button.DEFAULTS = {
   198      loadingText: 'loading...'
   199    }
   200  
   201    Button.prototype.setState = function (state) {
   202      var d    = 'disabled'
   203      var $el  = this.$element
   204      var val  = $el.is('input') ? 'val' : 'html'
   205      var data = $el.data()
   206  
   207      state = state + 'Text'
   208  
   209      if (data.resetText == null) $el.data('resetText', $el[val]())
   210  
   211      // push to event loop to allow forms to submit
   212      setTimeout($.proxy(function () {
   213        $el[val](data[state] == null ? this.options[state] : data[state])
   214  
   215        if (state == 'loadingText') {
   216          this.isLoading = true
   217          $el.addClass(d).attr(d, d)
   218        } else if (this.isLoading) {
   219          this.isLoading = false
   220          $el.removeClass(d).removeAttr(d)
   221        }
   222      }, this), 0)
   223    }
   224  
   225    Button.prototype.toggle = function () {
   226      var changed = true
   227      var $parent = this.$element.closest('[data-toggle="buttons"]')
   228  
   229      if ($parent.length) {
   230        var $input = this.$element.find('input')
   231        if ($input.prop('type') == 'radio') {
   232          if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
   233          else $parent.find('.active').removeClass('active')
   234        }
   235        if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
   236      } else {
   237        this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
   238      }
   239  
   240      if (changed) this.$element.toggleClass('active')
   241    }
   242  
   243  
   244    // BUTTON PLUGIN DEFINITION
   245    // ========================
   246  
   247    function Plugin(option) {
   248      return this.each(function () {
   249        var $this   = $(this)
   250        var data    = $this.data('bs.button')
   251        var options = typeof option == 'object' && option
   252  
   253        if (!data) $this.data('bs.button', (data = new Button(this, options)))
   254  
   255        if (option == 'toggle') data.toggle()
   256        else if (option) data.setState(option)
   257      })
   258    }
   259  
   260    var old = $.fn.button
   261  
   262    $.fn.button             = Plugin
   263    $.fn.button.Constructor = Button
   264  
   265  
   266    // BUTTON NO CONFLICT
   267    // ==================
   268  
   269    $.fn.button.noConflict = function () {
   270      $.fn.button = old
   271      return this
   272    }
   273  
   274  
   275    // BUTTON DATA-API
   276    // ===============
   277  
   278    $(document)
   279      .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
   280        var $btn = $(e.target)
   281        if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
   282        Plugin.call($btn, 'toggle')
   283        e.preventDefault()
   284      })
   285      .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
   286        $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
   287      })
   288  
   289  }(jQuery);
   290  
   291  /* ========================================================================
   292   * Bootstrap: carousel.js v3.3.2
   293   * http://getbootstrap.com/javascript/#carousel
   294   * ========================================================================
   295   * Copyright 2011-2015 Twitter, Inc.
   296   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   297   * ======================================================================== */
   298  
   299  
   300  +function ($) {
   301    'use strict';
   302  
   303    // CAROUSEL CLASS DEFINITION
   304    // =========================
   305  
   306    var Carousel = function (element, options) {
   307      this.$element    = $(element)
   308      this.$indicators = this.$element.find('.carousel-indicators')
   309      this.options     = options
   310      this.paused      =
   311      this.sliding     =
   312      this.interval    =
   313      this.$active     =
   314      this.$items      = null
   315  
   316      this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
   317  
   318      this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
   319        .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
   320        .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
   321    }
   322  
   323    Carousel.VERSION  = '3.3.2'
   324  
   325    Carousel.TRANSITION_DURATION = 600
   326  
   327    Carousel.DEFAULTS = {
   328      interval: 5000,
   329      pause: 'hover',
   330      wrap: true,
   331      keyboard: true
   332    }
   333  
   334    Carousel.prototype.keydown = function (e) {
   335      if (/input|textarea/i.test(e.target.tagName)) return
   336      switch (e.which) {
   337        case 37: this.prev(); break
   338        case 39: this.next(); break
   339        default: return
   340      }
   341  
   342      e.preventDefault()
   343    }
   344  
   345    Carousel.prototype.cycle = function (e) {
   346      e || (this.paused = false)
   347  
   348      this.interval && clearInterval(this.interval)
   349  
   350      this.options.interval
   351        && !this.paused
   352        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
   353  
   354      return this
   355    }
   356  
   357    Carousel.prototype.getItemIndex = function (item) {
   358      this.$items = item.parent().children('.item')
   359      return this.$items.index(item || this.$active)
   360    }
   361  
   362    Carousel.prototype.getItemForDirection = function (direction, active) {
   363      var activeIndex = this.getItemIndex(active)
   364      var willWrap = (direction == 'prev' && activeIndex === 0)
   365                  || (direction == 'next' && activeIndex == (this.$items.length - 1))
   366      if (willWrap && !this.options.wrap) return active
   367      var delta = direction == 'prev' ? -1 : 1
   368      var itemIndex = (activeIndex + delta) % this.$items.length
   369      return this.$items.eq(itemIndex)
   370    }
   371  
   372    Carousel.prototype.to = function (pos) {
   373      var that        = this
   374      var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
   375  
   376      if (pos > (this.$items.length - 1) || pos < 0) return
   377  
   378      if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
   379      if (activeIndex == pos) return this.pause().cycle()
   380  
   381      return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
   382    }
   383  
   384    Carousel.prototype.pause = function (e) {
   385      e || (this.paused = true)
   386  
   387      if (this.$element.find('.next, .prev').length && $.support.transition) {
   388        this.$element.trigger($.support.transition.end)
   389        this.cycle(true)
   390      }
   391  
   392      this.interval = clearInterval(this.interval)
   393  
   394      return this
   395    }
   396  
   397    Carousel.prototype.next = function () {
   398      if (this.sliding) return
   399      return this.slide('next')
   400    }
   401  
   402    Carousel.prototype.prev = function () {
   403      if (this.sliding) return
   404      return this.slide('prev')
   405    }
   406  
   407    Carousel.prototype.slide = function (type, next) {
   408      var $active   = this.$element.find('.item.active')
   409      var $next     = next || this.getItemForDirection(type, $active)
   410      var isCycling = this.interval
   411      var direction = type == 'next' ? 'left' : 'right'
   412      var that      = this
   413  
   414      if ($next.hasClass('active')) return (this.sliding = false)
   415  
   416      var relatedTarget = $next[0]
   417      var slideEvent = $.Event('slide.bs.carousel', {
   418        relatedTarget: relatedTarget,
   419        direction: direction
   420      })
   421      this.$element.trigger(slideEvent)
   422      if (slideEvent.isDefaultPrevented()) return
   423  
   424      this.sliding = true
   425  
   426      isCycling && this.pause()
   427  
   428      if (this.$indicators.length) {
   429        this.$indicators.find('.active').removeClass('active')
   430        var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
   431        $nextIndicator && $nextIndicator.addClass('active')
   432      }
   433  
   434      var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
   435      if ($.support.transition && this.$element.hasClass('slide')) {
   436        $next.addClass(type)
   437        $next[0].offsetWidth // force reflow
   438        $active.addClass(direction)
   439        $next.addClass(direction)
   440        $active
   441          .one('bsTransitionEnd', function () {
   442            $next.removeClass([type, direction].join(' ')).addClass('active')
   443            $active.removeClass(['active', direction].join(' '))
   444            that.sliding = false
   445            setTimeout(function () {
   446              that.$element.trigger(slidEvent)
   447            }, 0)
   448          })
   449          .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
   450      } else {
   451        $active.removeClass('active')
   452        $next.addClass('active')
   453        this.sliding = false
   454        this.$element.trigger(slidEvent)
   455      }
   456  
   457      isCycling && this.cycle()
   458  
   459      return this
   460    }
   461  
   462  
   463    // CAROUSEL PLUGIN DEFINITION
   464    // ==========================
   465  
   466    function Plugin(option) {
   467      return this.each(function () {
   468        var $this   = $(this)
   469        var data    = $this.data('bs.carousel')
   470        var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
   471        var action  = typeof option == 'string' ? option : options.slide
   472  
   473        if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
   474        if (typeof option == 'number') data.to(option)
   475        else if (action) data[action]()
   476        else if (options.interval) data.pause().cycle()
   477      })
   478    }
   479  
   480    var old = $.fn.carousel
   481  
   482    $.fn.carousel             = Plugin
   483    $.fn.carousel.Constructor = Carousel
   484  
   485  
   486    // CAROUSEL NO CONFLICT
   487    // ====================
   488  
   489    $.fn.carousel.noConflict = function () {
   490      $.fn.carousel = old
   491      return this
   492    }
   493  
   494  
   495    // CAROUSEL DATA-API
   496    // =================
   497  
   498    var clickHandler = function (e) {
   499      var href
   500      var $this   = $(this)
   501      var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
   502      if (!$target.hasClass('carousel')) return
   503      var options = $.extend({}, $target.data(), $this.data())
   504      var slideIndex = $this.attr('data-slide-to')
   505      if (slideIndex) options.interval = false
   506  
   507      Plugin.call($target, options)
   508  
   509      if (slideIndex) {
   510        $target.data('bs.carousel').to(slideIndex)
   511      }
   512  
   513      e.preventDefault()
   514    }
   515  
   516    $(document)
   517      .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
   518      .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
   519  
   520    $(window).on('load', function () {
   521      $('[data-ride="carousel"]').each(function () {
   522        var $carousel = $(this)
   523        Plugin.call($carousel, $carousel.data())
   524      })
   525    })
   526  
   527  }(jQuery);
   528  
   529  /* ========================================================================
   530   * Bootstrap: collapse.js v3.3.2
   531   * http://getbootstrap.com/javascript/#collapse
   532   * ========================================================================
   533   * Copyright 2011-2015 Twitter, Inc.
   534   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   535   * ======================================================================== */
   536  
   537  
   538  +function ($) {
   539    'use strict';
   540  
   541    // COLLAPSE PUBLIC CLASS DEFINITION
   542    // ================================
   543  
   544    var Collapse = function (element, options) {
   545      this.$element      = $(element)
   546      this.options       = $.extend({}, Collapse.DEFAULTS, options)
   547      this.$trigger      = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
   548      this.transitioning = null
   549  
   550      if (this.options.parent) {
   551        this.$parent = this.getParent()
   552      } else {
   553        this.addAriaAndCollapsedClass(this.$element, this.$trigger)
   554      }
   555  
   556      if (this.options.toggle) this.toggle()
   557    }
   558  
   559    Collapse.VERSION  = '3.3.2'
   560  
   561    Collapse.TRANSITION_DURATION = 350
   562  
   563    Collapse.DEFAULTS = {
   564      toggle: true,
   565      trigger: '[data-toggle="collapse"]'
   566    }
   567  
   568    Collapse.prototype.dimension = function () {
   569      var hasWidth = this.$element.hasClass('width')
   570      return hasWidth ? 'width' : 'height'
   571    }
   572  
   573    Collapse.prototype.show = function () {
   574      if (this.transitioning || this.$element.hasClass('in')) return
   575  
   576      var activesData
   577      var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
   578  
   579      if (actives && actives.length) {
   580        activesData = actives.data('bs.collapse')
   581        if (activesData && activesData.transitioning) return
   582      }
   583  
   584      var startEvent = $.Event('show.bs.collapse')
   585      this.$element.trigger(startEvent)
   586      if (startEvent.isDefaultPrevented()) return
   587  
   588      if (actives && actives.length) {
   589        Plugin.call(actives, 'hide')
   590        activesData || actives.data('bs.collapse', null)
   591      }
   592  
   593      var dimension = this.dimension()
   594  
   595      this.$element
   596        .removeClass('collapse')
   597        .addClass('collapsing')[dimension](0)
   598        .attr('aria-expanded', true)
   599  
   600      this.$trigger
   601        .removeClass('collapsed')
   602        .attr('aria-expanded', true)
   603  
   604      this.transitioning = 1
   605  
   606      var complete = function () {
   607        this.$element
   608          .removeClass('collapsing')
   609          .addClass('collapse in')[dimension]('')
   610        this.transitioning = 0
   611        this.$element
   612          .trigger('shown.bs.collapse')
   613      }
   614  
   615      if (!$.support.transition) return complete.call(this)
   616  
   617      var scrollSize = $.camelCase(['scroll', dimension].join('-'))
   618  
   619      this.$element
   620        .one('bsTransitionEnd', $.proxy(complete, this))
   621        .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
   622    }
   623  
   624    Collapse.prototype.hide = function () {
   625      if (this.transitioning || !this.$element.hasClass('in')) return
   626  
   627      var startEvent = $.Event('hide.bs.collapse')
   628      this.$element.trigger(startEvent)
   629      if (startEvent.isDefaultPrevented()) return
   630  
   631      var dimension = this.dimension()
   632  
   633      this.$element[dimension](this.$element[dimension]())[0].offsetHeight
   634  
   635      this.$element
   636        .addClass('collapsing')
   637        .removeClass('collapse in')
   638        .attr('aria-expanded', false)
   639  
   640      this.$trigger
   641        .addClass('collapsed')
   642        .attr('aria-expanded', false)
   643  
   644      this.transitioning = 1
   645  
   646      var complete = function () {
   647        this.transitioning = 0
   648        this.$element
   649          .removeClass('collapsing')
   650          .addClass('collapse')
   651          .trigger('hidden.bs.collapse')
   652      }
   653  
   654      if (!$.support.transition) return complete.call(this)
   655  
   656      this.$element
   657        [dimension](0)
   658        .one('bsTransitionEnd', $.proxy(complete, this))
   659        .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
   660    }
   661  
   662    Collapse.prototype.toggle = function () {
   663      this[this.$element.hasClass('in') ? 'hide' : 'show']()
   664    }
   665  
   666    Collapse.prototype.getParent = function () {
   667      return $(this.options.parent)
   668        .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
   669        .each($.proxy(function (i, element) {
   670          var $element = $(element)
   671          this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
   672        }, this))
   673        .end()
   674    }
   675  
   676    Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
   677      var isOpen = $element.hasClass('in')
   678  
   679      $element.attr('aria-expanded', isOpen)
   680      $trigger
   681        .toggleClass('collapsed', !isOpen)
   682        .attr('aria-expanded', isOpen)
   683    }
   684  
   685    function getTargetFromTrigger($trigger) {
   686      var href
   687      var target = $trigger.attr('data-target')
   688        || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
   689  
   690      return $(target)
   691    }
   692  
   693  
   694    // COLLAPSE PLUGIN DEFINITION
   695    // ==========================
   696  
   697    function Plugin(option) {
   698      return this.each(function () {
   699        var $this   = $(this)
   700        var data    = $this.data('bs.collapse')
   701        var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
   702  
   703        if (!data && options.toggle && option == 'show') options.toggle = false
   704        if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
   705        if (typeof option == 'string') data[option]()
   706      })
   707    }
   708  
   709    var old = $.fn.collapse
   710  
   711    $.fn.collapse             = Plugin
   712    $.fn.collapse.Constructor = Collapse
   713  
   714  
   715    // COLLAPSE NO CONFLICT
   716    // ====================
   717  
   718    $.fn.collapse.noConflict = function () {
   719      $.fn.collapse = old
   720      return this
   721    }
   722  
   723  
   724    // COLLAPSE DATA-API
   725    // =================
   726  
   727    $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
   728      var $this   = $(this)
   729  
   730      if (!$this.attr('data-target')) e.preventDefault()
   731  
   732      var $target = getTargetFromTrigger($this)
   733      var data    = $target.data('bs.collapse')
   734      var option  = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
   735  
   736      Plugin.call($target, option)
   737    })
   738  
   739  }(jQuery);
   740  
   741  /* ========================================================================
   742   * Bootstrap: dropdown.js v3.3.2
   743   * http://getbootstrap.com/javascript/#dropdowns
   744   * ========================================================================
   745   * Copyright 2011-2015 Twitter, Inc.
   746   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   747   * ======================================================================== */
   748  
   749  
   750  +function ($) {
   751    'use strict';
   752  
   753    // DROPDOWN CLASS DEFINITION
   754    // =========================
   755  
   756    var backdrop = '.dropdown-backdrop'
   757    var toggle   = '[data-toggle="dropdown"]'
   758    var Dropdown = function (element) {
   759      $(element).on('click.bs.dropdown', this.toggle)
   760    }
   761  
   762    Dropdown.VERSION = '3.3.2'
   763  
   764    Dropdown.prototype.toggle = function (e) {
   765      var $this = $(this)
   766  
   767      if ($this.is('.disabled, :disabled')) return
   768  
   769      var $parent  = getParent($this)
   770      var isActive = $parent.hasClass('open')
   771  
   772      clearMenus()
   773  
   774      if (!isActive) {
   775        if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
   776          // if mobile we use a backdrop because click events don't delegate
   777          $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
   778        }
   779  
   780        var relatedTarget = { relatedTarget: this }
   781        $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
   782  
   783        if (e.isDefaultPrevented()) return
   784  
   785        $this
   786          .trigger('focus')
   787          .attr('aria-expanded', 'true')
   788  
   789        $parent
   790          .toggleClass('open')
   791          .trigger('shown.bs.dropdown', relatedTarget)
   792      }
   793  
   794      return false
   795    }
   796  
   797    Dropdown.prototype.keydown = function (e) {
   798      if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
   799  
   800      var $this = $(this)
   801  
   802      e.preventDefault()
   803      e.stopPropagation()
   804  
   805      if ($this.is('.disabled, :disabled')) return
   806  
   807      var $parent  = getParent($this)
   808      var isActive = $parent.hasClass('open')
   809  
   810      if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
   811        if (e.which == 27) $parent.find(toggle).trigger('focus')
   812        return $this.trigger('click')
   813      }
   814  
   815      var desc = ' li:not(.divider):visible a'
   816      var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
   817  
   818      if (!$items.length) return
   819  
   820      var index = $items.index(e.target)
   821  
   822      if (e.which == 38 && index > 0)                 index--                        // up
   823      if (e.which == 40 && index < $items.length - 1) index++                        // down
   824      if (!~index)                                      index = 0
   825  
   826      $items.eq(index).trigger('focus')
   827    }
   828  
   829    function clearMenus(e) {
   830      if (e && e.which === 3) return
   831      $(backdrop).remove()
   832      $(toggle).each(function () {
   833        var $this         = $(this)
   834        var $parent       = getParent($this)
   835        var relatedTarget = { relatedTarget: this }
   836  
   837        if (!$parent.hasClass('open')) return
   838  
   839        $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
   840  
   841        if (e.isDefaultPrevented()) return
   842  
   843        $this.attr('aria-expanded', 'false')
   844        $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
   845      })
   846    }
   847  
   848    function getParent($this) {
   849      var selector = $this.attr('data-target')
   850  
   851      if (!selector) {
   852        selector = $this.attr('href')
   853        selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
   854      }
   855  
   856      var $parent = selector && $(selector)
   857  
   858      return $parent && $parent.length ? $parent : $this.parent()
   859    }
   860  
   861  
   862    // DROPDOWN PLUGIN DEFINITION
   863    // ==========================
   864  
   865    function Plugin(option) {
   866      return this.each(function () {
   867        var $this = $(this)
   868        var data  = $this.data('bs.dropdown')
   869  
   870        if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
   871        if (typeof option == 'string') data[option].call($this)
   872      })
   873    }
   874  
   875    var old = $.fn.dropdown
   876  
   877    $.fn.dropdown             = Plugin
   878    $.fn.dropdown.Constructor = Dropdown
   879  
   880  
   881    // DROPDOWN NO CONFLICT
   882    // ====================
   883  
   884    $.fn.dropdown.noConflict = function () {
   885      $.fn.dropdown = old
   886      return this
   887    }
   888  
   889  
   890    // APPLY TO STANDARD DROPDOWN ELEMENTS
   891    // ===================================
   892  
   893    $(document)
   894      .on('click.bs.dropdown.data-api', clearMenus)
   895      .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
   896      .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
   897      .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
   898      .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
   899      .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
   900  
   901  }(jQuery);
   902  
   903  /* ========================================================================
   904   * Bootstrap: modal.js v3.3.2
   905   * http://getbootstrap.com/javascript/#modals
   906   * ========================================================================
   907   * Copyright 2011-2015 Twitter, Inc.
   908   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
   909   * ======================================================================== */
   910  
   911  
   912  +function ($) {
   913    'use strict';
   914  
   915    // MODAL CLASS DEFINITION
   916    // ======================
   917  
   918    var Modal = function (element, options) {
   919      this.options        = options
   920      this.$body          = $(document.body)
   921      this.$element       = $(element)
   922      this.$backdrop      =
   923      this.isShown        = null
   924      this.scrollbarWidth = 0
   925  
   926      if (this.options.remote) {
   927        this.$element
   928          .find('.modal-content')
   929          .load(this.options.remote, $.proxy(function () {
   930            this.$element.trigger('loaded.bs.modal')
   931          }, this))
   932      }
   933    }
   934  
   935    Modal.VERSION  = '3.3.2'
   936  
   937    Modal.TRANSITION_DURATION = 300
   938    Modal.BACKDROP_TRANSITION_DURATION = 150
   939  
   940    Modal.DEFAULTS = {
   941      backdrop: true,
   942      keyboard: true,
   943      show: true
   944    }
   945  
   946    Modal.prototype.toggle = function (_relatedTarget) {
   947      return this.isShown ? this.hide() : this.show(_relatedTarget)
   948    }
   949  
   950    Modal.prototype.show = function (_relatedTarget) {
   951      var that = this
   952      var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
   953  
   954      this.$element.trigger(e)
   955  
   956      if (this.isShown || e.isDefaultPrevented()) return
   957  
   958      this.isShown = true
   959  
   960      this.checkScrollbar()
   961      this.setScrollbar()
   962      this.$body.addClass('modal-open')
   963  
   964      this.escape()
   965      this.resize()
   966  
   967      this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
   968  
   969      this.backdrop(function () {
   970        var transition = $.support.transition && that.$element.hasClass('fade')
   971  
   972        if (!that.$element.parent().length) {
   973          that.$element.appendTo(that.$body) // don't move modals dom position
   974        }
   975  
   976        that.$element
   977          .show()
   978          .scrollTop(0)
   979  
   980        if (that.options.backdrop) that.adjustBackdrop()
   981        that.adjustDialog()
   982  
   983        if (transition) {
   984          that.$element[0].offsetWidth // force reflow
   985        }
   986  
   987        that.$element
   988          .addClass('in')
   989          .attr('aria-hidden', false)
   990  
   991        that.enforceFocus()
   992  
   993        var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
   994  
   995        transition ?
   996          that.$element.find('.modal-dialog') // wait for modal to slide in
   997            .one('bsTransitionEnd', function () {
   998              that.$element.trigger('focus').trigger(e)
   999            })
  1000            .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  1001          that.$element.trigger('focus').trigger(e)
  1002      })
  1003    }
  1004  
  1005    Modal.prototype.hide = function (e) {
  1006      if (e) e.preventDefault()
  1007  
  1008      e = $.Event('hide.bs.modal')
  1009  
  1010      this.$element.trigger(e)
  1011  
  1012      if (!this.isShown || e.isDefaultPrevented()) return
  1013  
  1014      this.isShown = false
  1015  
  1016      this.escape()
  1017      this.resize()
  1018  
  1019      $(document).off('focusin.bs.modal')
  1020  
  1021      this.$element
  1022        .removeClass('in')
  1023        .attr('aria-hidden', true)
  1024        .off('click.dismiss.bs.modal')
  1025  
  1026      $.support.transition && this.$element.hasClass('fade') ?
  1027        this.$element
  1028          .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  1029          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
  1030        this.hideModal()
  1031    }
  1032  
  1033    Modal.prototype.enforceFocus = function () {
  1034      $(document)
  1035        .off('focusin.bs.modal') // guard against infinite focus loop
  1036        .on('focusin.bs.modal', $.proxy(function (e) {
  1037          if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  1038            this.$element.trigger('focus')
  1039          }
  1040        }, this))
  1041    }
  1042  
  1043    Modal.prototype.escape = function () {
  1044      if (this.isShown && this.options.keyboard) {
  1045        this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
  1046          e.which == 27 && this.hide()
  1047        }, this))
  1048      } else if (!this.isShown) {
  1049        this.$element.off('keydown.dismiss.bs.modal')
  1050      }
  1051    }
  1052  
  1053    Modal.prototype.resize = function () {
  1054      if (this.isShown) {
  1055        $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
  1056      } else {
  1057        $(window).off('resize.bs.modal')
  1058      }
  1059    }
  1060  
  1061    Modal.prototype.hideModal = function () {
  1062      var that = this
  1063      this.$element.hide()
  1064      this.backdrop(function () {
  1065        that.$body.removeClass('modal-open')
  1066        that.resetAdjustments()
  1067        that.resetScrollbar()
  1068        that.$element.trigger('hidden.bs.modal')
  1069      })
  1070    }
  1071  
  1072    Modal.prototype.removeBackdrop = function () {
  1073      this.$backdrop && this.$backdrop.remove()
  1074      this.$backdrop = null
  1075    }
  1076  
  1077    Modal.prototype.backdrop = function (callback) {
  1078      var that = this
  1079      var animate = this.$element.hasClass('fade') ? 'fade' : ''
  1080  
  1081      if (this.isShown && this.options.backdrop) {
  1082        var doAnimate = $.support.transition && animate
  1083  
  1084        this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
  1085          .prependTo(this.$element)
  1086          .on('click.dismiss.bs.modal', $.proxy(function (e) {
  1087            if (e.target !== e.currentTarget) return
  1088            this.options.backdrop == 'static'
  1089              ? this.$element[0].focus.call(this.$element[0])
  1090              : this.hide.call(this)
  1091          }, this))
  1092  
  1093        if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  1094  
  1095        this.$backdrop.addClass('in')
  1096  
  1097        if (!callback) return
  1098  
  1099        doAnimate ?
  1100          this.$backdrop
  1101            .one('bsTransitionEnd', callback)
  1102            .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  1103          callback()
  1104  
  1105      } else if (!this.isShown && this.$backdrop) {
  1106        this.$backdrop.removeClass('in')
  1107  
  1108        var callbackRemove = function () {
  1109          that.removeBackdrop()
  1110          callback && callback()
  1111        }
  1112        $.support.transition && this.$element.hasClass('fade') ?
  1113          this.$backdrop
  1114            .one('bsTransitionEnd', callbackRemove)
  1115            .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
  1116          callbackRemove()
  1117  
  1118      } else if (callback) {
  1119        callback()
  1120      }
  1121    }
  1122  
  1123    // these following methods are used to handle overflowing modals
  1124  
  1125    Modal.prototype.handleUpdate = function () {
  1126      if (this.options.backdrop) this.adjustBackdrop()
  1127      this.adjustDialog()
  1128    }
  1129  
  1130    Modal.prototype.adjustBackdrop = function () {
  1131      this.$backdrop
  1132        .css('height', 0)
  1133        .css('height', this.$element[0].scrollHeight)
  1134    }
  1135  
  1136    Modal.prototype.adjustDialog = function () {
  1137      var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
  1138  
  1139      this.$element.css({
  1140        paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
  1141        paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
  1142      })
  1143    }
  1144  
  1145    Modal.prototype.resetAdjustments = function () {
  1146      this.$element.css({
  1147        paddingLeft: '',
  1148        paddingRight: ''
  1149      })
  1150    }
  1151  
  1152    Modal.prototype.checkScrollbar = function () {
  1153      this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
  1154      this.scrollbarWidth = this.measureScrollbar()
  1155    }
  1156  
  1157    Modal.prototype.setScrollbar = function () {
  1158      var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  1159      if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  1160    }
  1161  
  1162    Modal.prototype.resetScrollbar = function () {
  1163      this.$body.css('padding-right', '')
  1164    }
  1165  
  1166    Modal.prototype.measureScrollbar = function () { // thx walsh
  1167      var scrollDiv = document.createElement('div')
  1168      scrollDiv.className = 'modal-scrollbar-measure'
  1169      this.$body.append(scrollDiv)
  1170      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  1171      this.$body[0].removeChild(scrollDiv)
  1172      return scrollbarWidth
  1173    }
  1174  
  1175  
  1176    // MODAL PLUGIN DEFINITION
  1177    // =======================
  1178  
  1179    function Plugin(option, _relatedTarget) {
  1180      return this.each(function () {
  1181        var $this   = $(this)
  1182        var data    = $this.data('bs.modal')
  1183        var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  1184  
  1185        if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  1186        if (typeof option == 'string') data[option](_relatedTarget)
  1187        else if (options.show) data.show(_relatedTarget)
  1188      })
  1189    }
  1190  
  1191    var old = $.fn.modal
  1192  
  1193    $.fn.modal             = Plugin
  1194    $.fn.modal.Constructor = Modal
  1195  
  1196  
  1197    // MODAL NO CONFLICT
  1198    // =================
  1199  
  1200    $.fn.modal.noConflict = function () {
  1201      $.fn.modal = old
  1202      return this
  1203    }
  1204  
  1205  
  1206    // MODAL DATA-API
  1207    // ==============
  1208  
  1209    $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  1210      var $this   = $(this)
  1211      var href    = $this.attr('href')
  1212      var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
  1213      var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  1214  
  1215      if ($this.is('a')) e.preventDefault()
  1216  
  1217      $target.one('show.bs.modal', function (showEvent) {
  1218        if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
  1219        $target.one('hidden.bs.modal', function () {
  1220          $this.is(':visible') && $this.trigger('focus')
  1221        })
  1222      })
  1223      Plugin.call($target, option, this)
  1224    })
  1225  
  1226  }(jQuery);
  1227  
  1228  /* ========================================================================
  1229   * Bootstrap: tooltip.js v3.3.2
  1230   * http://getbootstrap.com/javascript/#tooltip
  1231   * Inspired by the original jQuery.tipsy by Jason Frame
  1232   * ========================================================================
  1233   * Copyright 2011-2015 Twitter, Inc.
  1234   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1235   * ======================================================================== */
  1236  
  1237  
  1238  +function ($) {
  1239    'use strict';
  1240  
  1241    // TOOLTIP PUBLIC CLASS DEFINITION
  1242    // ===============================
  1243  
  1244    var Tooltip = function (element, options) {
  1245      this.type       =
  1246      this.options    =
  1247      this.enabled    =
  1248      this.timeout    =
  1249      this.hoverState =
  1250      this.$element   = null
  1251  
  1252      this.init('tooltip', element, options)
  1253    }
  1254  
  1255    Tooltip.VERSION  = '3.3.2'
  1256  
  1257    Tooltip.TRANSITION_DURATION = 150
  1258  
  1259    Tooltip.DEFAULTS = {
  1260      animation: true,
  1261      placement: 'top',
  1262      selector: false,
  1263      template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
  1264      trigger: 'hover focus',
  1265      title: '',
  1266      delay: 0,
  1267      html: false,
  1268      container: false,
  1269      viewport: {
  1270        selector: 'body',
  1271        padding: 0
  1272      }
  1273    }
  1274  
  1275    Tooltip.prototype.init = function (type, element, options) {
  1276      this.enabled   = true
  1277      this.type      = type
  1278      this.$element  = $(element)
  1279      this.options   = this.getOptions(options)
  1280      this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
  1281  
  1282      var triggers = this.options.trigger.split(' ')
  1283  
  1284      for (var i = triggers.length; i--;) {
  1285        var trigger = triggers[i]
  1286  
  1287        if (trigger == 'click') {
  1288          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  1289        } else if (trigger != 'manual') {
  1290          var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
  1291          var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
  1292  
  1293          this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
  1294          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  1295        }
  1296      }
  1297  
  1298      this.options.selector ?
  1299        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  1300        this.fixTitle()
  1301    }
  1302  
  1303    Tooltip.prototype.getDefaults = function () {
  1304      return Tooltip.DEFAULTS
  1305    }
  1306  
  1307    Tooltip.prototype.getOptions = function (options) {
  1308      options = $.extend({}, this.getDefaults(), this.$element.data(), options)
  1309  
  1310      if (options.delay && typeof options.delay == 'number') {
  1311        options.delay = {
  1312          show: options.delay,
  1313          hide: options.delay
  1314        }
  1315      }
  1316  
  1317      return options
  1318    }
  1319  
  1320    Tooltip.prototype.getDelegateOptions = function () {
  1321      var options  = {}
  1322      var defaults = this.getDefaults()
  1323  
  1324      this._options && $.each(this._options, function (key, value) {
  1325        if (defaults[key] != value) options[key] = value
  1326      })
  1327  
  1328      return options
  1329    }
  1330  
  1331    Tooltip.prototype.enter = function (obj) {
  1332      var self = obj instanceof this.constructor ?
  1333        obj : $(obj.currentTarget).data('bs.' + this.type)
  1334  
  1335      if (self && self.$tip && self.$tip.is(':visible')) {
  1336        self.hoverState = 'in'
  1337        return
  1338      }
  1339  
  1340      if (!self) {
  1341        self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  1342        $(obj.currentTarget).data('bs.' + this.type, self)
  1343      }
  1344  
  1345      clearTimeout(self.timeout)
  1346  
  1347      self.hoverState = 'in'
  1348  
  1349      if (!self.options.delay || !self.options.delay.show) return self.show()
  1350  
  1351      self.timeout = setTimeout(function () {
  1352        if (self.hoverState == 'in') self.show()
  1353      }, self.options.delay.show)
  1354    }
  1355  
  1356    Tooltip.prototype.leave = function (obj) {
  1357      var self = obj instanceof this.constructor ?
  1358        obj : $(obj.currentTarget).data('bs.' + this.type)
  1359  
  1360      if (!self) {
  1361        self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  1362        $(obj.currentTarget).data('bs.' + this.type, self)
  1363      }
  1364  
  1365      clearTimeout(self.timeout)
  1366  
  1367      self.hoverState = 'out'
  1368  
  1369      if (!self.options.delay || !self.options.delay.hide) return self.hide()
  1370  
  1371      self.timeout = setTimeout(function () {
  1372        if (self.hoverState == 'out') self.hide()
  1373      }, self.options.delay.hide)
  1374    }
  1375  
  1376    Tooltip.prototype.show = function () {
  1377      var e = $.Event('show.bs.' + this.type)
  1378  
  1379      if (this.hasContent() && this.enabled) {
  1380        this.$element.trigger(e)
  1381  
  1382        var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
  1383        if (e.isDefaultPrevented() || !inDom) return
  1384        var that = this
  1385  
  1386        var $tip = this.tip()
  1387  
  1388        var tipId = this.getUID(this.type)
  1389  
  1390        this.setContent()
  1391        $tip.attr('id', tipId)
  1392        this.$element.attr('aria-describedby', tipId)
  1393  
  1394        if (this.options.animation) $tip.addClass('fade')
  1395  
  1396        var placement = typeof this.options.placement == 'function' ?
  1397          this.options.placement.call(this, $tip[0], this.$element[0]) :
  1398          this.options.placement
  1399  
  1400        var autoToken = /\s?auto?\s?/i
  1401        var autoPlace = autoToken.test(placement)
  1402        if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
  1403  
  1404        $tip
  1405          .detach()
  1406          .css({ top: 0, left: 0, display: 'block' })
  1407          .addClass(placement)
  1408          .data('bs.' + this.type, this)
  1409  
  1410        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  1411  
  1412        var pos          = this.getPosition()
  1413        var actualWidth  = $tip[0].offsetWidth
  1414        var actualHeight = $tip[0].offsetHeight
  1415  
  1416        if (autoPlace) {
  1417          var orgPlacement = placement
  1418          var $container   = this.options.container ? $(this.options.container) : this.$element.parent()
  1419          var containerDim = this.getPosition($container)
  1420  
  1421          placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top'    :
  1422                      placement == 'top'    && pos.top    - actualHeight < containerDim.top    ? 'bottom' :
  1423                      placement == 'right'  && pos.right  + actualWidth  > containerDim.width  ? 'left'   :
  1424                      placement == 'left'   && pos.left   - actualWidth  < containerDim.left   ? 'right'  :
  1425                      placement
  1426  
  1427          $tip
  1428            .removeClass(orgPlacement)
  1429            .addClass(placement)
  1430        }
  1431  
  1432        var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  1433  
  1434        this.applyPlacement(calculatedOffset, placement)
  1435  
  1436        var complete = function () {
  1437          var prevHoverState = that.hoverState
  1438          that.$element.trigger('shown.bs.' + that.type)
  1439          that.hoverState = null
  1440  
  1441          if (prevHoverState == 'out') that.leave(that)
  1442        }
  1443  
  1444        $.support.transition && this.$tip.hasClass('fade') ?
  1445          $tip
  1446            .one('bsTransitionEnd', complete)
  1447            .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  1448          complete()
  1449      }
  1450    }
  1451  
  1452    Tooltip.prototype.applyPlacement = function (offset, placement) {
  1453      var $tip   = this.tip()
  1454      var width  = $tip[0].offsetWidth
  1455      var height = $tip[0].offsetHeight
  1456  
  1457      // manually read margins because getBoundingClientRect includes difference
  1458      var marginTop = parseInt($tip.css('margin-top'), 10)
  1459      var marginLeft = parseInt($tip.css('margin-left'), 10)
  1460  
  1461      // we must check for NaN for ie 8/9
  1462      if (isNaN(marginTop))  marginTop  = 0
  1463      if (isNaN(marginLeft)) marginLeft = 0
  1464  
  1465      offset.top  = offset.top  + marginTop
  1466      offset.left = offset.left + marginLeft
  1467  
  1468      // $.fn.offset doesn't round pixel values
  1469      // so we use setOffset directly with our own function B-0
  1470      $.offset.setOffset($tip[0], $.extend({
  1471        using: function (props) {
  1472          $tip.css({
  1473            top: Math.round(props.top),
  1474            left: Math.round(props.left)
  1475          })
  1476        }
  1477      }, offset), 0)
  1478  
  1479      $tip.addClass('in')
  1480  
  1481      // check to see if placing tip in new offset caused the tip to resize itself
  1482      var actualWidth  = $tip[0].offsetWidth
  1483      var actualHeight = $tip[0].offsetHeight
  1484  
  1485      if (placement == 'top' && actualHeight != height) {
  1486        offset.top = offset.top + height - actualHeight
  1487      }
  1488  
  1489      var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
  1490  
  1491      if (delta.left) offset.left += delta.left
  1492      else offset.top += delta.top
  1493  
  1494      var isVertical          = /top|bottom/.test(placement)
  1495      var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
  1496      var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
  1497  
  1498      $tip.offset(offset)
  1499      this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  1500    }
  1501  
  1502    Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
  1503      this.arrow()
  1504        .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
  1505        .css(isHorizontal ? 'top' : 'left', '')
  1506    }
  1507  
  1508    Tooltip.prototype.setContent = function () {
  1509      var $tip  = this.tip()
  1510      var title = this.getTitle()
  1511  
  1512      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
  1513      $tip.removeClass('fade in top bottom left right')
  1514    }
  1515  
  1516    Tooltip.prototype.hide = function (callback) {
  1517      var that = this
  1518      var $tip = this.tip()
  1519      var e    = $.Event('hide.bs.' + this.type)
  1520  
  1521      function complete() {
  1522        if (that.hoverState != 'in') $tip.detach()
  1523        that.$element
  1524          .removeAttr('aria-describedby')
  1525          .trigger('hidden.bs.' + that.type)
  1526        callback && callback()
  1527      }
  1528  
  1529      this.$element.trigger(e)
  1530  
  1531      if (e.isDefaultPrevented()) return
  1532  
  1533      $tip.removeClass('in')
  1534  
  1535      $.support.transition && this.$tip.hasClass('fade') ?
  1536        $tip
  1537          .one('bsTransitionEnd', complete)
  1538          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
  1539        complete()
  1540  
  1541      this.hoverState = null
  1542  
  1543      return this
  1544    }
  1545  
  1546    Tooltip.prototype.fixTitle = function () {
  1547      var $e = this.$element
  1548      if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
  1549        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
  1550      }
  1551    }
  1552  
  1553    Tooltip.prototype.hasContent = function () {
  1554      return this.getTitle()
  1555    }
  1556  
  1557    Tooltip.prototype.getPosition = function ($element) {
  1558      $element   = $element || this.$element
  1559  
  1560      var el     = $element[0]
  1561      var isBody = el.tagName == 'BODY'
  1562  
  1563      var elRect    = el.getBoundingClientRect()
  1564      if (elRect.width == null) {
  1565        // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
  1566        elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
  1567      }
  1568      var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
  1569      var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
  1570      var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
  1571  
  1572      return $.extend({}, elRect, scroll, outerDims, elOffset)
  1573    }
  1574  
  1575    Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
  1576      return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
  1577             placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
  1578             placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
  1579          /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
  1580  
  1581    }
  1582  
  1583    Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
  1584      var delta = { top: 0, left: 0 }
  1585      if (!this.$viewport) return delta
  1586  
  1587      var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
  1588      var viewportDimensions = this.getPosition(this.$viewport)
  1589  
  1590      if (/right|left/.test(placement)) {
  1591        var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
  1592        var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
  1593        if (topEdgeOffset < viewportDimensions.top) { // top overflow
  1594          delta.top = viewportDimensions.top - topEdgeOffset
  1595        } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
  1596          delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
  1597        }
  1598      } else {
  1599        var leftEdgeOffset  = pos.left - viewportPadding
  1600        var rightEdgeOffset = pos.left + viewportPadding + actualWidth
  1601        if (leftEdgeOffset < viewportDimensions.left) { // left overflow
  1602          delta.left = viewportDimensions.left - leftEdgeOffset
  1603        } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
  1604          delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
  1605        }
  1606      }
  1607  
  1608      return delta
  1609    }
  1610  
  1611    Tooltip.prototype.getTitle = function () {
  1612      var title
  1613      var $e = this.$element
  1614      var o  = this.options
  1615  
  1616      title = $e.attr('data-original-title')
  1617        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
  1618  
  1619      return title
  1620    }
  1621  
  1622    Tooltip.prototype.getUID = function (prefix) {
  1623      do prefix += ~~(Math.random() * 1000000)
  1624      while (document.getElementById(prefix))
  1625      return prefix
  1626    }
  1627  
  1628    Tooltip.prototype.tip = function () {
  1629      return (this.$tip = this.$tip || $(this.options.template))
  1630    }
  1631  
  1632    Tooltip.prototype.arrow = function () {
  1633      return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  1634    }
  1635  
  1636    Tooltip.prototype.enable = function () {
  1637      this.enabled = true
  1638    }
  1639  
  1640    Tooltip.prototype.disable = function () {
  1641      this.enabled = false
  1642    }
  1643  
  1644    Tooltip.prototype.toggleEnabled = function () {
  1645      this.enabled = !this.enabled
  1646    }
  1647  
  1648    Tooltip.prototype.toggle = function (e) {
  1649      var self = this
  1650      if (e) {
  1651        self = $(e.currentTarget).data('bs.' + this.type)
  1652        if (!self) {
  1653          self = new this.constructor(e.currentTarget, this.getDelegateOptions())
  1654          $(e.currentTarget).data('bs.' + this.type, self)
  1655        }
  1656      }
  1657  
  1658      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  1659    }
  1660  
  1661    Tooltip.prototype.destroy = function () {
  1662      var that = this
  1663      clearTimeout(this.timeout)
  1664      this.hide(function () {
  1665        that.$element.off('.' + that.type).removeData('bs.' + that.type)
  1666      })
  1667    }
  1668  
  1669  
  1670    // TOOLTIP PLUGIN DEFINITION
  1671    // =========================
  1672  
  1673    function Plugin(option) {
  1674      return this.each(function () {
  1675        var $this   = $(this)
  1676        var data    = $this.data('bs.tooltip')
  1677        var options = typeof option == 'object' && option
  1678  
  1679        if (!data && option == 'destroy') return
  1680        if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
  1681        if (typeof option == 'string') data[option]()
  1682      })
  1683    }
  1684  
  1685    var old = $.fn.tooltip
  1686  
  1687    $.fn.tooltip             = Plugin
  1688    $.fn.tooltip.Constructor = Tooltip
  1689  
  1690  
  1691    // TOOLTIP NO CONFLICT
  1692    // ===================
  1693  
  1694    $.fn.tooltip.noConflict = function () {
  1695      $.fn.tooltip = old
  1696      return this
  1697    }
  1698  
  1699  }(jQuery);
  1700  
  1701  /* ========================================================================
  1702   * Bootstrap: popover.js v3.3.2
  1703   * http://getbootstrap.com/javascript/#popovers
  1704   * ========================================================================
  1705   * Copyright 2011-2015 Twitter, Inc.
  1706   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1707   * ======================================================================== */
  1708  
  1709  
  1710  +function ($) {
  1711    'use strict';
  1712  
  1713    // POPOVER PUBLIC CLASS DEFINITION
  1714    // ===============================
  1715  
  1716    var Popover = function (element, options) {
  1717      this.init('popover', element, options)
  1718    }
  1719  
  1720    if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
  1721  
  1722    Popover.VERSION  = '3.3.2'
  1723  
  1724    Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
  1725      placement: 'right',
  1726      trigger: 'click',
  1727      content: '',
  1728      template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  1729    })
  1730  
  1731  
  1732    // NOTE: POPOVER EXTENDS tooltip.js
  1733    // ================================
  1734  
  1735    Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
  1736  
  1737    Popover.prototype.constructor = Popover
  1738  
  1739    Popover.prototype.getDefaults = function () {
  1740      return Popover.DEFAULTS
  1741    }
  1742  
  1743    Popover.prototype.setContent = function () {
  1744      var $tip    = this.tip()
  1745      var title   = this.getTitle()
  1746      var content = this.getContent()
  1747  
  1748      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
  1749      $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
  1750        this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
  1751      ](content)
  1752  
  1753      $tip.removeClass('fade top bottom left right in')
  1754  
  1755      // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
  1756      // this manually by checking the contents.
  1757      if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  1758    }
  1759  
  1760    Popover.prototype.hasContent = function () {
  1761      return this.getTitle() || this.getContent()
  1762    }
  1763  
  1764    Popover.prototype.getContent = function () {
  1765      var $e = this.$element
  1766      var o  = this.options
  1767  
  1768      return $e.attr('data-content')
  1769        || (typeof o.content == 'function' ?
  1770              o.content.call($e[0]) :
  1771              o.content)
  1772    }
  1773  
  1774    Popover.prototype.arrow = function () {
  1775      return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  1776    }
  1777  
  1778    Popover.prototype.tip = function () {
  1779      if (!this.$tip) this.$tip = $(this.options.template)
  1780      return this.$tip
  1781    }
  1782  
  1783  
  1784    // POPOVER PLUGIN DEFINITION
  1785    // =========================
  1786  
  1787    function Plugin(option) {
  1788      return this.each(function () {
  1789        var $this   = $(this)
  1790        var data    = $this.data('bs.popover')
  1791        var options = typeof option == 'object' && option
  1792  
  1793        if (!data && option == 'destroy') return
  1794        if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
  1795        if (typeof option == 'string') data[option]()
  1796      })
  1797    }
  1798  
  1799    var old = $.fn.popover
  1800  
  1801    $.fn.popover             = Plugin
  1802    $.fn.popover.Constructor = Popover
  1803  
  1804  
  1805    // POPOVER NO CONFLICT
  1806    // ===================
  1807  
  1808    $.fn.popover.noConflict = function () {
  1809      $.fn.popover = old
  1810      return this
  1811    }
  1812  
  1813  }(jQuery);
  1814  
  1815  /* ========================================================================
  1816   * Bootstrap: scrollspy.js v3.3.2
  1817   * http://getbootstrap.com/javascript/#scrollspy
  1818   * ========================================================================
  1819   * Copyright 2011-2015 Twitter, Inc.
  1820   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1821   * ======================================================================== */
  1822  
  1823  
  1824  +function ($) {
  1825    'use strict';
  1826  
  1827    // SCROLLSPY CLASS DEFINITION
  1828    // ==========================
  1829  
  1830    function ScrollSpy(element, options) {
  1831      var process  = $.proxy(this.process, this)
  1832  
  1833      this.$body          = $('body')
  1834      this.$scrollElement = $(element).is('body') ? $(window) : $(element)
  1835      this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
  1836      this.selector       = (this.options.target || '') + ' .nav li > a'
  1837      this.offsets        = []
  1838      this.targets        = []
  1839      this.activeTarget   = null
  1840      this.scrollHeight   = 0
  1841  
  1842      this.$scrollElement.on('scroll.bs.scrollspy', process)
  1843      this.refresh()
  1844      this.process()
  1845    }
  1846  
  1847    ScrollSpy.VERSION  = '3.3.2'
  1848  
  1849    ScrollSpy.DEFAULTS = {
  1850      offset: 10
  1851    }
  1852  
  1853    ScrollSpy.prototype.getScrollHeight = function () {
  1854      return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  1855    }
  1856  
  1857    ScrollSpy.prototype.refresh = function () {
  1858      var offsetMethod = 'offset'
  1859      var offsetBase   = 0
  1860  
  1861      if (!$.isWindow(this.$scrollElement[0])) {
  1862        offsetMethod = 'position'
  1863        offsetBase   = this.$scrollElement.scrollTop()
  1864      }
  1865  
  1866      this.offsets = []
  1867      this.targets = []
  1868      this.scrollHeight = this.getScrollHeight()
  1869  
  1870      var self     = this
  1871  
  1872      this.$body
  1873        .find(this.selector)
  1874        .map(function () {
  1875          var $el   = $(this)
  1876          var href  = $el.data('target') || $el.attr('href')
  1877          var $href = /^#./.test(href) && $(href)
  1878  
  1879          return ($href
  1880            && $href.length
  1881            && $href.is(':visible')
  1882            && [[$href[offsetMethod]().top + offsetBase, href]]) || null
  1883        })
  1884        .sort(function (a, b) { return a[0] - b[0] })
  1885        .each(function () {
  1886          self.offsets.push(this[0])
  1887          self.targets.push(this[1])
  1888        })
  1889    }
  1890  
  1891    ScrollSpy.prototype.process = function () {
  1892      var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
  1893      var scrollHeight = this.getScrollHeight()
  1894      var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
  1895      var offsets      = this.offsets
  1896      var targets      = this.targets
  1897      var activeTarget = this.activeTarget
  1898      var i
  1899  
  1900      if (this.scrollHeight != scrollHeight) {
  1901        this.refresh()
  1902      }
  1903  
  1904      if (scrollTop >= maxScroll) {
  1905        return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  1906      }
  1907  
  1908      if (activeTarget && scrollTop < offsets[0]) {
  1909        this.activeTarget = null
  1910        return this.clear()
  1911      }
  1912  
  1913      for (i = offsets.length; i--;) {
  1914        activeTarget != targets[i]
  1915          && scrollTop >= offsets[i]
  1916          && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
  1917          && this.activate(targets[i])
  1918      }
  1919    }
  1920  
  1921    ScrollSpy.prototype.activate = function (target) {
  1922      this.activeTarget = target
  1923  
  1924      this.clear()
  1925  
  1926      var selector = this.selector +
  1927          '[data-target="' + target + '"],' +
  1928          this.selector + '[href="' + target + '"]'
  1929  
  1930      var active = $(selector)
  1931        .parents('li')
  1932        .addClass('active')
  1933  
  1934      if (active.parent('.dropdown-menu').length) {
  1935        active = active
  1936          .closest('li.dropdown')
  1937          .addClass('active')
  1938      }
  1939  
  1940      active.trigger('activate.bs.scrollspy')
  1941    }
  1942  
  1943    ScrollSpy.prototype.clear = function () {
  1944      $(this.selector)
  1945        .parentsUntil(this.options.target, '.active')
  1946        .removeClass('active')
  1947    }
  1948  
  1949  
  1950    // SCROLLSPY PLUGIN DEFINITION
  1951    // ===========================
  1952  
  1953    function Plugin(option) {
  1954      return this.each(function () {
  1955        var $this   = $(this)
  1956        var data    = $this.data('bs.scrollspy')
  1957        var options = typeof option == 'object' && option
  1958  
  1959        if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
  1960        if (typeof option == 'string') data[option]()
  1961      })
  1962    }
  1963  
  1964    var old = $.fn.scrollspy
  1965  
  1966    $.fn.scrollspy             = Plugin
  1967    $.fn.scrollspy.Constructor = ScrollSpy
  1968  
  1969  
  1970    // SCROLLSPY NO CONFLICT
  1971    // =====================
  1972  
  1973    $.fn.scrollspy.noConflict = function () {
  1974      $.fn.scrollspy = old
  1975      return this
  1976    }
  1977  
  1978  
  1979    // SCROLLSPY DATA-API
  1980    // ==================
  1981  
  1982    $(window).on('load.bs.scrollspy.data-api', function () {
  1983      $('[data-spy="scroll"]').each(function () {
  1984        var $spy = $(this)
  1985        Plugin.call($spy, $spy.data())
  1986      })
  1987    })
  1988  
  1989  }(jQuery);
  1990  
  1991  /* ========================================================================
  1992   * Bootstrap: tab.js v3.3.2
  1993   * http://getbootstrap.com/javascript/#tabs
  1994   * ========================================================================
  1995   * Copyright 2011-2015 Twitter, Inc.
  1996   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  1997   * ======================================================================== */
  1998  
  1999  
  2000  +function ($) {
  2001    'use strict';
  2002  
  2003    // TAB CLASS DEFINITION
  2004    // ====================
  2005  
  2006    var Tab = function (element) {
  2007      this.element = $(element)
  2008    }
  2009  
  2010    Tab.VERSION = '3.3.2'
  2011  
  2012    Tab.TRANSITION_DURATION = 150
  2013  
  2014    Tab.prototype.show = function () {
  2015      var $this    = this.element
  2016      var $ul      = $this.closest('ul:not(.dropdown-menu)')
  2017      var selector = $this.data('target')
  2018  
  2019      if (!selector) {
  2020        selector = $this.attr('href')
  2021        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  2022      }
  2023  
  2024      if ($this.parent('li').hasClass('active')) return
  2025  
  2026      var $previous = $ul.find('.active:last a')
  2027      var hideEvent = $.Event('hide.bs.tab', {
  2028        relatedTarget: $this[0]
  2029      })
  2030      var showEvent = $.Event('show.bs.tab', {
  2031        relatedTarget: $previous[0]
  2032      })
  2033  
  2034      $previous.trigger(hideEvent)
  2035      $this.trigger(showEvent)
  2036  
  2037      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
  2038  
  2039      var $target = $(selector)
  2040  
  2041      this.activate($this.closest('li'), $ul)
  2042      this.activate($target, $target.parent(), function () {
  2043        $previous.trigger({
  2044          type: 'hidden.bs.tab',
  2045          relatedTarget: $this[0]
  2046        })
  2047        $this.trigger({
  2048          type: 'shown.bs.tab',
  2049          relatedTarget: $previous[0]
  2050        })
  2051      })
  2052    }
  2053  
  2054    Tab.prototype.activate = function (element, container, callback) {
  2055      var $active    = container.find('> .active')
  2056      var transition = callback
  2057        && $.support.transition
  2058        && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
  2059  
  2060      function next() {
  2061        $active
  2062          .removeClass('active')
  2063          .find('> .dropdown-menu > .active')
  2064            .removeClass('active')
  2065          .end()
  2066          .find('[data-toggle="tab"]')
  2067            .attr('aria-expanded', false)
  2068  
  2069        element
  2070          .addClass('active')
  2071          .find('[data-toggle="tab"]')
  2072            .attr('aria-expanded', true)
  2073  
  2074        if (transition) {
  2075          element[0].offsetWidth // reflow for transition
  2076          element.addClass('in')
  2077        } else {
  2078          element.removeClass('fade')
  2079        }
  2080  
  2081        if (element.parent('.dropdown-menu')) {
  2082          element
  2083            .closest('li.dropdown')
  2084              .addClass('active')
  2085            .end()
  2086            .find('[data-toggle="tab"]')
  2087              .attr('aria-expanded', true)
  2088        }
  2089  
  2090        callback && callback()
  2091      }
  2092  
  2093      $active.length && transition ?
  2094        $active
  2095          .one('bsTransitionEnd', next)
  2096          .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
  2097        next()
  2098  
  2099      $active.removeClass('in')
  2100    }
  2101  
  2102  
  2103    // TAB PLUGIN DEFINITION
  2104    // =====================
  2105  
  2106    function Plugin(option) {
  2107      return this.each(function () {
  2108        var $this = $(this)
  2109        var data  = $this.data('bs.tab')
  2110  
  2111        if (!data) $this.data('bs.tab', (data = new Tab(this)))
  2112        if (typeof option == 'string') data[option]()
  2113      })
  2114    }
  2115  
  2116    var old = $.fn.tab
  2117  
  2118    $.fn.tab             = Plugin
  2119    $.fn.tab.Constructor = Tab
  2120  
  2121  
  2122    // TAB NO CONFLICT
  2123    // ===============
  2124  
  2125    $.fn.tab.noConflict = function () {
  2126      $.fn.tab = old
  2127      return this
  2128    }
  2129  
  2130  
  2131    // TAB DATA-API
  2132    // ============
  2133  
  2134    var clickHandler = function (e) {
  2135      e.preventDefault()
  2136      Plugin.call($(this), 'show')
  2137    }
  2138  
  2139    $(document)
  2140      .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
  2141      .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
  2142  
  2143  }(jQuery);
  2144  
  2145  /* ========================================================================
  2146   * Bootstrap: affix.js v3.3.2
  2147   * http://getbootstrap.com/javascript/#affix
  2148   * ========================================================================
  2149   * Copyright 2011-2015 Twitter, Inc.
  2150   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  2151   * ======================================================================== */
  2152  
  2153  
  2154  +function ($) {
  2155    'use strict';
  2156  
  2157    // AFFIX CLASS DEFINITION
  2158    // ======================
  2159  
  2160    var Affix = function (element, options) {
  2161      this.options = $.extend({}, Affix.DEFAULTS, options)
  2162  
  2163      this.$target = $(this.options.target)
  2164        .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
  2165        .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
  2166  
  2167      this.$element     = $(element)
  2168      this.affixed      =
  2169      this.unpin        =
  2170      this.pinnedOffset = null
  2171  
  2172      this.checkPosition()
  2173    }
  2174  
  2175    Affix.VERSION  = '3.3.2'
  2176  
  2177    Affix.RESET    = 'affix affix-top affix-bottom'
  2178  
  2179    Affix.DEFAULTS = {
  2180      offset: 0,
  2181      target: window
  2182    }
  2183  
  2184    Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
  2185      var scrollTop    = this.$target.scrollTop()
  2186      var position     = this.$element.offset()
  2187      var targetHeight = this.$target.height()
  2188  
  2189      if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
  2190  
  2191      if (this.affixed == 'bottom') {
  2192        if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
  2193        return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
  2194      }
  2195  
  2196      var initializing   = this.affixed == null
  2197      var colliderTop    = initializing ? scrollTop : position.top
  2198      var colliderHeight = initializing ? targetHeight : height
  2199  
  2200      if (offsetTop != null && scrollTop <= offsetTop) return 'top'
  2201      if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
  2202  
  2203      return false
  2204    }
  2205  
  2206    Affix.prototype.getPinnedOffset = function () {
  2207      if (this.pinnedOffset) return this.pinnedOffset
  2208      this.$element.removeClass(Affix.RESET).addClass('affix')
  2209      var scrollTop = this.$target.scrollTop()
  2210      var position  = this.$element.offset()
  2211      return (this.pinnedOffset = position.top - scrollTop)
  2212    }
  2213  
  2214    Affix.prototype.checkPositionWithEventLoop = function () {
  2215      setTimeout($.proxy(this.checkPosition, this), 1)
  2216    }
  2217  
  2218    Affix.prototype.checkPosition = function () {
  2219      if (!this.$element.is(':visible')) return
  2220  
  2221      var height       = this.$element.height()
  2222      var offset       = this.options.offset
  2223      var offsetTop    = offset.top
  2224      var offsetBottom = offset.bottom
  2225      var scrollHeight = $('body').height()
  2226  
  2227      if (typeof offset != 'object')         offsetBottom = offsetTop = offset
  2228      if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
  2229      if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
  2230  
  2231      var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
  2232  
  2233      if (this.affixed != affix) {
  2234        if (this.unpin != null) this.$element.css('top', '')
  2235  
  2236        var affixType = 'affix' + (affix ? '-' + affix : '')
  2237        var e         = $.Event(affixType + '.bs.affix')
  2238  
  2239        this.$element.trigger(e)
  2240  
  2241        if (e.isDefaultPrevented()) return
  2242  
  2243        this.affixed = affix
  2244        this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
  2245  
  2246        this.$element
  2247          .removeClass(Affix.RESET)
  2248          .addClass(affixType)
  2249          .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
  2250      }
  2251  
  2252      if (affix == 'bottom') {
  2253        this.$element.offset({
  2254          top: scrollHeight - height - offsetBottom
  2255        })
  2256      }
  2257    }
  2258  
  2259  
  2260    // AFFIX PLUGIN DEFINITION
  2261    // =======================
  2262  
  2263    function Plugin(option) {
  2264      return this.each(function () {
  2265        var $this   = $(this)
  2266        var data    = $this.data('bs.affix')
  2267        var options = typeof option == 'object' && option
  2268  
  2269        if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
  2270        if (typeof option == 'string') data[option]()
  2271      })
  2272    }
  2273  
  2274    var old = $.fn.affix
  2275  
  2276    $.fn.affix             = Plugin
  2277    $.fn.affix.Constructor = Affix
  2278  
  2279  
  2280    // AFFIX NO CONFLICT
  2281    // =================
  2282  
  2283    $.fn.affix.noConflict = function () {
  2284      $.fn.affix = old
  2285      return this
  2286    }
  2287  
  2288  
  2289    // AFFIX DATA-API
  2290    // ==============
  2291  
  2292    $(window).on('load', function () {
  2293      $('[data-spy="affix"]').each(function () {
  2294        var $spy = $(this)
  2295        var data = $spy.data()
  2296  
  2297        data.offset = data.offset || {}
  2298  
  2299        if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
  2300        if (data.offsetTop    != null) data.offset.top    = data.offsetTop
  2301  
  2302        Plugin.call($spy, data)
  2303      })
  2304    })
  2305  
  2306  }(jQuery);