bootstrap.js 65.6 KB
Newer Older
XhmikosR's avatar
XhmikosR committed
1001
1002
    })
  }
1003

XhmikosR's avatar
XhmikosR committed
1004
1005
  Modal.prototype.hide = function (e) {
    if (e) e.preventDefault()
1006

XhmikosR's avatar
XhmikosR committed
1007
    e = $.Event('hide.bs.modal')
fat's avatar
build    
fat committed
1008

XhmikosR's avatar
XhmikosR committed
1009
    this.$element.trigger(e)
1010

XhmikosR's avatar
XhmikosR committed
1011
    if (!this.isShown || e.isDefaultPrevented()) return
1012

XhmikosR's avatar
XhmikosR committed
1013
    this.isShown = false
1014

XhmikosR's avatar
XhmikosR committed
1015
    this.escape()
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1016
    this.resize()
Chris Rebert's avatar
Chris Rebert committed
1017

XhmikosR's avatar
XhmikosR committed
1018
    $(document).off('focusin.bs.modal')
Chris Rebert's avatar
Chris Rebert committed
1019

XhmikosR's avatar
XhmikosR committed
1020
1021
1022
1023
    this.$element
      .removeClass('in')
      .attr('aria-hidden', true)
      .off('click.dismiss.bs.modal')
1024

XhmikosR's avatar
XhmikosR committed
1025
1026
1027
    $.support.transition && this.$element.hasClass('fade') ?
      this.$element
        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1028
        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
XhmikosR's avatar
XhmikosR committed
1029
1030
      this.hideModal()
  }
1031

XhmikosR's avatar
XhmikosR committed
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
  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.trigger('focus')
        }
      }, this))
  }

  Modal.prototype.escape = function () {
    if (this.isShown && this.options.keyboard) {
Mark Otto's avatar
grunt    
Mark Otto committed
1044
      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
XhmikosR's avatar
XhmikosR committed
1045
1046
1047
        e.which == 27 && this.hide()
      }, this))
    } else if (!this.isShown) {
Mark Otto's avatar
grunt    
Mark Otto committed
1048
      this.$element.off('keydown.dismiss.bs.modal')
XhmikosR's avatar
XhmikosR committed
1049
1050
1051
    }
  }

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1052
1053
  Modal.prototype.resize = function () {
    if (this.isShown) {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1054
      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1055
1056
1057
1058
1059
    } else {
      $(window).off('resize.bs.modal')
    }
  }

XhmikosR's avatar
XhmikosR committed
1060
1061
1062
1063
  Modal.prototype.hideModal = function () {
    var that = this
    this.$element.hide()
    this.backdrop(function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1064
      that.$body.removeClass('modal-open')
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1065
      that.resetAdjustments()
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1066
      that.resetScrollbar()
XhmikosR's avatar
XhmikosR committed
1067
1068
1069
      that.$element.trigger('hidden.bs.modal')
    })
  }
1070

XhmikosR's avatar
XhmikosR committed
1071
1072
1073
1074
  Modal.prototype.removeBackdrop = function () {
    this.$backdrop && this.$backdrop.remove()
    this.$backdrop = null
  }
1075

XhmikosR's avatar
XhmikosR committed
1076
1077
1078
  Modal.prototype.backdrop = function (callback) {
    var that = this
    var animate = this.$element.hasClass('fade') ? 'fade' : ''
1079

XhmikosR's avatar
XhmikosR committed
1080
1081
    if (this.isShown && this.options.backdrop) {
      var doAnimate = $.support.transition && animate
1082

XhmikosR's avatar
XhmikosR committed
1083
      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
1084
1085
1086
1087
1088
1089
1090
        .prependTo(this.$element)
        .on('click.dismiss.bs.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))
1091

XhmikosR's avatar
XhmikosR committed
1092
      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1093

XhmikosR's avatar
XhmikosR committed
1094
      this.$backdrop.addClass('in')
1095

XhmikosR's avatar
XhmikosR committed
1096
      if (!callback) return
1097

XhmikosR's avatar
XhmikosR committed
1098
1099
1100
      doAnimate ?
        this.$backdrop
          .one('bsTransitionEnd', callback)
1101
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
XhmikosR's avatar
XhmikosR committed
1102
        callback()
1103

XhmikosR's avatar
XhmikosR committed
1104
1105
    } else if (!this.isShown && this.$backdrop) {
      this.$backdrop.removeClass('in')
Chris Rebert's avatar
Chris Rebert committed
1106

XhmikosR's avatar
XhmikosR committed
1107
1108
1109
      var callbackRemove = function () {
        that.removeBackdrop()
        callback && callback()
Chris Rebert's avatar
Chris Rebert committed
1110
      }
XhmikosR's avatar
XhmikosR committed
1111
1112
1113
      $.support.transition && this.$element.hasClass('fade') ?
        this.$backdrop
          .one('bsTransitionEnd', callbackRemove)
1114
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
XhmikosR's avatar
XhmikosR committed
1115
        callbackRemove()
1116

XhmikosR's avatar
XhmikosR committed
1117
1118
    } else if (callback) {
      callback()
Chris Rebert's avatar
Chris Rebert committed
1119
    }
XhmikosR's avatar
XhmikosR committed
1120
  }
1121

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1122
1123
1124
1125
1126
1127
1128
1129
  // these following methods are used to handle overflowing modals

  Modal.prototype.handleUpdate = function () {
    if (this.options.backdrop) this.adjustBackdrop()
    this.adjustDialog()
  }

  Modal.prototype.adjustBackdrop = function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1130
1131
1132
1133
1134
    this.$backdrop
      .css('height', 0)
      .css('height', this.$element[0].scrollHeight)
  }

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  Modal.prototype.adjustDialog = function () {
    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight

    this.$element.css({
      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
    })
  }

  Modal.prototype.resetAdjustments = function () {
    this.$element.css({
      paddingLeft: '',
      paddingRight: ''
    })
  }

XhmikosR's avatar
XhmikosR committed
1151
  Modal.prototype.checkScrollbar = function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1152
    this.bodyIsOverflowing = document.body.scrollHeight > document.documentElement.clientHeight
Mark Otto's avatar
grunt    
Mark Otto committed
1153
    this.scrollbarWidth = this.measureScrollbar()
XhmikosR's avatar
XhmikosR committed
1154
  }
fat's avatar
build    
fat committed
1155

XhmikosR's avatar
XhmikosR committed
1156
1157
  Modal.prototype.setScrollbar = function () {
    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1158
    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
XhmikosR's avatar
XhmikosR committed
1159
  }
fat's avatar
build    
fat committed
1160

XhmikosR's avatar
XhmikosR committed
1161
1162
1163
  Modal.prototype.resetScrollbar = function () {
    this.$body.css('padding-right', '')
  }
fat's avatar
build    
fat committed
1164

XhmikosR's avatar
XhmikosR committed
1165
1166
1167
1168
1169
1170
1171
1172
  Modal.prototype.measureScrollbar = function () { // thx walsh
    var scrollDiv = document.createElement('div')
    scrollDiv.className = 'modal-scrollbar-measure'
    this.$body.append(scrollDiv)
    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
    this.$body[0].removeChild(scrollDiv)
    return scrollbarWidth
  }
1173
1174


XhmikosR's avatar
XhmikosR committed
1175
1176
  // MODAL PLUGIN DEFINITION
  // =======================
fat's avatar
fat committed
1177

XhmikosR's avatar
XhmikosR committed
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  function Plugin(option, _relatedTarget) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.modal')
      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)

      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
      if (typeof option == 'string') data[option](_relatedTarget)
      else if (options.show) data.show(_relatedTarget)
    })
  }
1189

XhmikosR's avatar
XhmikosR committed
1190
  var old = $.fn.modal
Mark Otto's avatar
Mark Otto committed
1191

XhmikosR's avatar
XhmikosR committed
1192
1193
  $.fn.modal             = Plugin
  $.fn.modal.Constructor = Modal
1194
1195


XhmikosR's avatar
XhmikosR committed
1196
1197
  // MODAL NO CONFLICT
  // =================
1198

XhmikosR's avatar
XhmikosR committed
1199
1200
1201
1202
  $.fn.modal.noConflict = function () {
    $.fn.modal = old
    return this
  }
1203
1204


XhmikosR's avatar
XhmikosR committed
1205
1206
  // MODAL DATA-API
  // ==============
1207

XhmikosR's avatar
XhmikosR committed
1208
1209
1210
1211
1212
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
    var $this   = $(this)
    var href    = $this.attr('href')
    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1213

XhmikosR's avatar
XhmikosR committed
1214
    if ($this.is('a')) e.preventDefault()
1215

XhmikosR's avatar
XhmikosR committed
1216
1217
1218
1219
    $target.one('show.bs.modal', function (showEvent) {
      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
      $target.one('hidden.bs.modal', function () {
        $this.is(':visible') && $this.trigger('focus')
Mark Otto's avatar
grunt    
Mark Otto committed
1220
      })
Mark Otto's avatar
Mark Otto committed
1221
    })
XhmikosR's avatar
XhmikosR committed
1222
    Plugin.call($target, option, this)
Jacob Thornton's avatar
Jacob Thornton committed
1223
  })
1224

XhmikosR's avatar
XhmikosR committed
1225
}(jQuery);
1226

1227
/* ========================================================================
Mark Otto's avatar
Mark Otto committed
1228
 * Bootstrap: tooltip.js v3.3.1
Mark Otto's avatar
Mark Otto committed
1229
 * http://getbootstrap.com/javascript/#tooltip
1230
 * Inspired by the original jQuery.tipsy by Jason Frame
1231
 * ========================================================================
1232
 * Copyright 2011-2014 Twitter, Inc.
1233
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1234
 * ======================================================================== */
1235
1236


XhmikosR's avatar
XhmikosR committed
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
+function ($) {
  'use strict';

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null

    this.init('tooltip', element, options)
  }

Mark Otto's avatar
Mark Otto committed
1254
  Tooltip.VERSION  = '3.3.1'
XhmikosR's avatar
XhmikosR committed
1255

1256
1257
  Tooltip.TRANSITION_DURATION = 150

XhmikosR's avatar
XhmikosR committed
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
  Tooltip.DEFAULTS = {
    animation: true,
    placement: 'top',
    selector: false,
    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
    trigger: 'hover focus',
    title: '',
    delay: 0,
    html: false,
    container: false,
    viewport: {
      selector: 'body',
      padding: 0
    }
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled   = true
    this.type      = type
    this.$element  = $(element)
    this.options   = this.getOptions(options)
    this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }
1296

XhmikosR's avatar
XhmikosR committed
1297
1298
1299
1300
    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }
1301

XhmikosR's avatar
XhmikosR committed
1302
1303
1304
  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }
1305

XhmikosR's avatar
XhmikosR committed
1306
1307
  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1308

XhmikosR's avatar
XhmikosR committed
1309
1310
1311
1312
    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay,
        hide: options.delay
1313
1314
      }
    }
1315

XhmikosR's avatar
XhmikosR committed
1316
1317
    return options
  }
Jacob Thornton's avatar
Jacob Thornton committed
1318

XhmikosR's avatar
XhmikosR committed
1319
1320
1321
  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()
1322

XhmikosR's avatar
XhmikosR committed
1323
1324
1325
    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })
fat's avatar
rebuild    
fat committed
1326

XhmikosR's avatar
XhmikosR committed
1327
1328
    return options
  }
Jacob Thornton's avatar
Jacob Thornton committed
1329

XhmikosR's avatar
XhmikosR committed
1330
1331
1332
  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)
Mark Otto's avatar
Mark Otto committed
1333

XhmikosR's avatar
XhmikosR committed
1334
1335
1336
1337
1338
    if (self && self.$tip && self.$tip.is(':visible')) {
      self.hoverState = 'in'
      return
    }

XhmikosR's avatar
XhmikosR committed
1339
1340
1341
    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
Mark Otto's avatar
Mark Otto committed
1342
    }
1343

XhmikosR's avatar
XhmikosR committed
1344
    clearTimeout(self.timeout)
1345

XhmikosR's avatar
XhmikosR committed
1346
    self.hoverState = 'in'
1347

XhmikosR's avatar
XhmikosR committed
1348
    if (!self.options.delay || !self.options.delay.show) return self.show()
1349

XhmikosR's avatar
XhmikosR committed
1350
1351
1352
1353
    self.timeout = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }
1354

XhmikosR's avatar
XhmikosR committed
1355
1356
1357
  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)
Mark Otto's avatar
Mark Otto committed
1358

XhmikosR's avatar
XhmikosR committed
1359
1360
1361
    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
Mark Otto's avatar
Mark Otto committed
1362
    }
1363

XhmikosR's avatar
XhmikosR committed
1364
    clearTimeout(self.timeout)
fat's avatar
fat committed
1365

XhmikosR's avatar
XhmikosR committed
1366
    self.hoverState = 'out'
1367

XhmikosR's avatar
XhmikosR committed
1368
    if (!self.options.delay || !self.options.delay.hide) return self.hide()
1369

XhmikosR's avatar
XhmikosR committed
1370
1371
1372
1373
    self.timeout = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }
1374

XhmikosR's avatar
XhmikosR committed
1375
1376
  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.' + this.type)
Chris Rebert's avatar
Chris Rebert committed
1377

XhmikosR's avatar
XhmikosR committed
1378
1379
    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)
fat's avatar
fat committed
1380

Heinrich Fenkart's avatar
Heinrich Fenkart committed
1381
      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
XhmikosR's avatar
XhmikosR committed
1382
1383
      if (e.isDefaultPrevented() || !inDom) return
      var that = this
1384

XhmikosR's avatar
XhmikosR committed
1385
      var $tip = this.tip()
fat's avatar
fat committed
1386

XhmikosR's avatar
XhmikosR committed
1387
      var tipId = this.getUID(this.type)
fat's avatar
fat committed
1388

XhmikosR's avatar
XhmikosR committed
1389
1390
1391
      this.setContent()
      $tip.attr('id', tipId)
      this.$element.attr('aria-describedby', tipId)
1392

XhmikosR's avatar
XhmikosR committed
1393
      if (this.options.animation) $tip.addClass('fade')
1394

XhmikosR's avatar
XhmikosR committed
1395
1396
1397
      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement
1398

XhmikosR's avatar
XhmikosR committed
1399
1400
1401
      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1402

XhmikosR's avatar
XhmikosR committed
1403
1404
1405
1406
1407
      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
        .data('bs.' + this.type, this)
fat's avatar
fat committed
1408

XhmikosR's avatar
XhmikosR committed
1409
      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1410

XhmikosR's avatar
XhmikosR committed
1411
1412
1413
      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight
Chris Rebert's avatar
Chris Rebert committed
1414

XhmikosR's avatar
XhmikosR committed
1415
1416
      if (autoPlace) {
        var orgPlacement = placement
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1417
1418
        var $container   = this.options.container ? $(this.options.container) : this.$element.parent()
        var containerDim = this.getPosition($container)
Chris Rebert's avatar
Chris Rebert committed
1419

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1420
1421
1422
1423
        placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top'    :
                    placement == 'top'    && pos.top    - actualHeight < containerDim.top    ? 'bottom' :
                    placement == 'right'  && pos.right  + actualWidth  > containerDim.width  ? 'left'   :
                    placement == 'left'   && pos.left   - actualWidth  < containerDim.left   ? 'right'  :
XhmikosR's avatar
XhmikosR committed
1424
                    placement
fat's avatar
fat committed
1425

1426
        $tip
XhmikosR's avatar
XhmikosR committed
1427
          .removeClass(orgPlacement)
1428
          .addClass(placement)
XhmikosR's avatar
XhmikosR committed
1429
      }
1430

XhmikosR's avatar
XhmikosR committed
1431
      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1432

XhmikosR's avatar
XhmikosR committed
1433
      this.applyPlacement(calculatedOffset, placement)
fat's avatar
fat committed
1434

XhmikosR's avatar
XhmikosR committed
1435
      var complete = function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1436
        var prevHoverState = that.hoverState
XhmikosR's avatar
XhmikosR committed
1437
1438
        that.$element.trigger('shown.bs.' + that.type)
        that.hoverState = null
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1439
1440

        if (prevHoverState == 'out') that.leave(that)
XhmikosR's avatar
XhmikosR committed
1441
      }
fat's avatar
fat committed
1442

XhmikosR's avatar
XhmikosR committed
1443
1444
1445
      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
1446
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
XhmikosR's avatar
XhmikosR committed
1447
1448
1449
        complete()
    }
  }
fat's avatar
fat committed
1450

XhmikosR's avatar
XhmikosR committed
1451
1452
1453
1454
  Tooltip.prototype.applyPlacement = function (offset, placement) {
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight
fat's avatar
fat committed
1455

XhmikosR's avatar
XhmikosR committed
1456
1457
1458
    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)
fat's avatar
fat committed
1459

XhmikosR's avatar
XhmikosR committed
1460
1461
1462
    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0
fat's avatar
fat committed
1463

XhmikosR's avatar
XhmikosR committed
1464
1465
    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft
fat's avatar
fat committed
1466

XhmikosR's avatar
XhmikosR committed
1467
1468
1469
1470
1471
1472
1473
1474
    // $.fn.offset doesn't round pixel values
    // so we use setOffset directly with our own function B-0
    $.offset.setOffset($tip[0], $.extend({
      using: function (props) {
        $tip.css({
          top: Math.round(props.top),
          left: Math.round(props.left)
        })
1475
      }
XhmikosR's avatar
XhmikosR committed
1476
    }, offset), 0)
1477

XhmikosR's avatar
XhmikosR committed
1478
    $tip.addClass('in')
fat's avatar
fat committed
1479

XhmikosR's avatar
XhmikosR committed
1480
1481
1482
    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight
fat's avatar
fat committed
1483

XhmikosR's avatar
XhmikosR committed
1484
1485
1486
    if (placement == 'top' && actualHeight != height) {
      offset.top = offset.top + height - actualHeight
    }
fat's avatar
fat committed
1487

XhmikosR's avatar
XhmikosR committed
1488
    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
fat's avatar
fat committed
1489

XhmikosR's avatar
XhmikosR committed
1490
1491
    if (delta.left) offset.left += delta.left
    else offset.top += delta.top
1492

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1493
1494
1495
    var isVertical          = /top|bottom/.test(placement)
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1496

XhmikosR's avatar
XhmikosR committed
1497
    $tip.offset(offset)
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1498
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
XhmikosR's avatar
XhmikosR committed
1499
  }
1500

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1501
1502
1503
1504
  Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
    this.arrow()
      .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
      .css(isHorizontal ? 'top' : 'left', '')
XhmikosR's avatar
XhmikosR committed
1505
  }
1506

XhmikosR's avatar
XhmikosR committed
1507
1508
1509
  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()
1510

XhmikosR's avatar
XhmikosR committed
1511
1512
1513
    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }
1514

Heinrich Fenkart's avatar
Heinrich Fenkart committed
1515
  Tooltip.prototype.hide = function (callback) {
XhmikosR's avatar
XhmikosR committed
1516
1517
1518
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)
1519

XhmikosR's avatar
XhmikosR committed
1520
1521
    function complete() {
      if (that.hoverState != 'in') $tip.detach()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
1522
1523
1524
      that.$element
        .removeAttr('aria-describedby')
        .trigger('hidden.bs.' + that.type)
Heinrich Fenkart's avatar
Heinrich Fenkart committed
1525
      callback && callback()
XhmikosR's avatar
XhmikosR committed
1526
    }
Jacob Thornton's avatar
Jacob Thornton committed
1527

XhmikosR's avatar
XhmikosR committed
1528
    this.$element.trigger(e)
1529

XhmikosR's avatar
XhmikosR committed
1530
    if (e.isDefaultPrevented()) return
1531

XhmikosR's avatar
XhmikosR committed
1532
    $tip.removeClass('in')
1533

XhmikosR's avatar
XhmikosR committed
1534
1535
1536
    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
        .one('bsTransitionEnd', complete)
1537
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
XhmikosR's avatar
XhmikosR committed
1538
      complete()
1539

XhmikosR's avatar
XhmikosR committed
1540
    this.hoverState = null
1541

XhmikosR's avatar
XhmikosR committed
1542
1543
    return this
  }
1544

XhmikosR's avatar
XhmikosR committed
1545
1546
1547
1548
  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1549
    }
XhmikosR's avatar
XhmikosR committed
1550
  }
1551

XhmikosR's avatar
XhmikosR committed
1552
1553
1554
  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }
1555

XhmikosR's avatar
XhmikosR committed
1556
1557
  Tooltip.prototype.getPosition = function ($element) {
    $element   = $element || this.$element
Mark Otto's avatar
grunt    
Mark Otto committed
1558

XhmikosR's avatar
XhmikosR committed
1559
1560
    var el     = $element[0]
    var isBody = el.tagName == 'BODY'
Mark Otto's avatar
grunt    
Mark Otto committed
1561

Mark Otto's avatar
grunt    
Mark Otto committed
1562
    var elRect    = el.getBoundingClientRect()
Heinrich Fenkart's avatar
Heinrich Fenkart committed
1563
1564
1565
1566
    if (elRect.width == null) {
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
    }
Mark Otto's avatar
grunt    
Mark Otto committed
1567
1568
    var elOffset  = isBody ? { top: 0, left: 0 } : $element.offset()
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1569
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
Mark Otto's avatar
grunt    
Mark Otto committed
1570
1571

    return $.extend({}, elRect, scroll, outerDims, elOffset)
XhmikosR's avatar
XhmikosR committed
1572
  }
1573

XhmikosR's avatar
XhmikosR committed
1574
1575
1576
1577
1578
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
1579

XhmikosR's avatar
XhmikosR committed
1580
  }
1581

XhmikosR's avatar
XhmikosR committed
1582
1583
1584
  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
    var delta = { top: 0, left: 0 }
    if (!this.$viewport) return delta
1585

XhmikosR's avatar
XhmikosR committed
1586
1587
    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
    var viewportDimensions = this.getPosition(this.$viewport)
1588

XhmikosR's avatar
XhmikosR committed
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
    if (/right|left/.test(placement)) {
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
        delta.top = viewportDimensions.top - topEdgeOffset
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
      }
    } else {
      var leftEdgeOffset  = pos.left - viewportPadding
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
        delta.left = viewportDimensions.left - leftEdgeOffset
      } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1604
      }
Chris Rebert's avatar
Chris Rebert committed
1605
    }
fat's avatar
fat committed
1606

XhmikosR's avatar
XhmikosR committed
1607
1608
    return delta
  }
1609

XhmikosR's avatar
XhmikosR committed
1610
1611
1612
1613
  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options
1614

XhmikosR's avatar
XhmikosR committed
1615
1616
    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
1617

XhmikosR's avatar
XhmikosR committed
1618
1619
    return title
  }
1620

XhmikosR's avatar
XhmikosR committed
1621
1622
1623
1624
1625
  Tooltip.prototype.getUID = function (prefix) {
    do prefix += ~~(Math.random() * 1000000)
    while (document.getElementById(prefix))
    return prefix
  }
1626

XhmikosR's avatar
XhmikosR committed
1627
1628
1629
  Tooltip.prototype.tip = function () {
    return (this.$tip = this.$tip || $(this.options.template))
  }
1630

XhmikosR's avatar
XhmikosR committed
1631
1632
1633
  Tooltip.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  }
1634

XhmikosR's avatar
XhmikosR committed
1635
1636
1637
  Tooltip.prototype.enable = function () {
    this.enabled = true
  }
1638

XhmikosR's avatar
XhmikosR committed
1639
1640
1641
  Tooltip.prototype.disable = function () {
    this.enabled = false
  }
Mark Otto's avatar
Mark Otto committed
1642

XhmikosR's avatar
XhmikosR committed
1643
1644
1645
  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }
Chris Rebert's avatar
Chris Rebert committed
1646

XhmikosR's avatar
XhmikosR committed
1647
1648
1649
1650
1651
1652
1653
1654
  Tooltip.prototype.toggle = function (e) {
    var self = this
    if (e) {
      self = $(e.currentTarget).data('bs.' + this.type)
      if (!self) {
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
        $(e.currentTarget).data('bs.' + this.type, self)
      }
Mark Otto's avatar
Mark Otto committed
1655
1656
    }

XhmikosR's avatar
XhmikosR committed
1657
1658
    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }
1659

XhmikosR's avatar
XhmikosR committed
1660
  Tooltip.prototype.destroy = function () {
Heinrich Fenkart's avatar
Heinrich Fenkart committed
1661
    var that = this
XhmikosR's avatar
XhmikosR committed
1662
    clearTimeout(this.timeout)
Heinrich Fenkart's avatar
Heinrich Fenkart committed
1663
1664
1665
    this.hide(function () {
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
    })
XhmikosR's avatar
XhmikosR committed
1666
  }
1667
1668


XhmikosR's avatar
XhmikosR committed
1669
1670
  // TOOLTIP PLUGIN DEFINITION
  // =========================
1671

XhmikosR's avatar
XhmikosR committed
1672
1673
  function Plugin(option) {
    return this.each(function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1674
1675
1676
1677
      var $this    = $(this)
      var data     = $this.data('bs.tooltip')
      var options  = typeof option == 'object' && option
      var selector = options && options.selector
fat's avatar
fat committed
1678

XhmikosR's avatar
XhmikosR committed
1679
      if (!data && option == 'destroy') return
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1680
1681
1682
1683
1684
1685
      if (selector) {
        if (!data) $this.data('bs.tooltip', (data = {}))
        if (!data[selector]) data[selector] = new Tooltip(this, options)
      } else {
        if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      }
XhmikosR's avatar
XhmikosR committed
1686
1687
1688
      if (typeof option == 'string') data[option]()
    })
  }
1689

XhmikosR's avatar
XhmikosR committed
1690
  var old = $.fn.tooltip
Mark Otto's avatar
Mark Otto committed
1691

XhmikosR's avatar
XhmikosR committed
1692
1693
  $.fn.tooltip             = Plugin
  $.fn.tooltip.Constructor = Tooltip
1694

1695

XhmikosR's avatar
XhmikosR committed
1696
1697
  // TOOLTIP NO CONFLICT
  // ===================
1698

XhmikosR's avatar
XhmikosR committed
1699
1700
1701
1702
  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }
1703

XhmikosR's avatar
XhmikosR committed
1704
}(jQuery);
1705

1706
/* ========================================================================
Mark Otto's avatar
Mark Otto committed
1707
 * Bootstrap: popover.js v3.3.1
Mark Otto's avatar
Mark Otto committed
1708
 * http://getbootstrap.com/javascript/#popovers
1709
 * ========================================================================
1710
 * Copyright 2011-2014 Twitter, Inc.
1711
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1712
 * ======================================================================== */
1713
1714


XhmikosR's avatar
XhmikosR committed
1715
1716
+function ($) {
  'use strict';
Mark Otto's avatar
grunt    
Mark Otto committed
1717

XhmikosR's avatar
XhmikosR committed
1718
1719
  // POPOVER PUBLIC CLASS DEFINITION
  // ===============================
1720

XhmikosR's avatar
XhmikosR committed
1721
1722
1723
  var Popover = function (element, options) {
    this.init('popover', element, options)
  }
fat's avatar
fat committed
1724

XhmikosR's avatar
XhmikosR committed
1725
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1726

Mark Otto's avatar
Mark Otto committed
1727
  Popover.VERSION  = '3.3.1'
1728

XhmikosR's avatar
XhmikosR committed
1729
1730
1731
1732
1733
1734
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
    placement: 'right',
    trigger: 'click',
    content: '',
    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  })
fat's avatar
fat committed
1735
1736


XhmikosR's avatar
XhmikosR committed
1737
1738
  // NOTE: POPOVER EXTENDS tooltip.js
  // ================================
1739

XhmikosR's avatar
XhmikosR committed
1740
  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
fat's avatar
fat committed
1741

XhmikosR's avatar
XhmikosR committed
1742
  Popover.prototype.constructor = Popover
1743

XhmikosR's avatar
XhmikosR committed
1744
1745
1746
  Popover.prototype.getDefaults = function () {
    return Popover.DEFAULTS
  }
1747

XhmikosR's avatar
XhmikosR committed
1748
1749
1750
1751
  Popover.prototype.setContent = function () {
    var $tip    = this.tip()
    var title   = this.getTitle()
    var content = this.getContent()
1752

XhmikosR's avatar
XhmikosR committed
1753
    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
Mark Otto's avatar
grunt    
Mark Otto committed
1754
    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
XhmikosR's avatar
XhmikosR committed
1755
1756
      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
    ](content)
1757

XhmikosR's avatar
XhmikosR committed
1758
    $tip.removeClass('fade top bottom left right in')
1759

XhmikosR's avatar
XhmikosR committed
1760
1761
1762
1763
    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
    // this manually by checking the contents.
    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  }
1764

XhmikosR's avatar
XhmikosR committed
1765
1766
1767
  Popover.prototype.hasContent = function () {
    return this.getTitle() || this.getContent()
  }
1768

XhmikosR's avatar
XhmikosR committed
1769
1770
1771
  Popover.prototype.getContent = function () {
    var $e = this.$element
    var o  = this.options
1772

XhmikosR's avatar
XhmikosR committed
1773
1774
1775
1776
1777
    return $e.attr('data-content')
      || (typeof o.content == 'function' ?
            o.content.call($e[0]) :
            o.content)
  }
fat's avatar
fat committed
1778

XhmikosR's avatar
XhmikosR committed
1779
1780
1781
  Popover.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  }
1782

XhmikosR's avatar
XhmikosR committed
1783
1784
1785
1786
  Popover.prototype.tip = function () {
    if (!this.$tip) this.$tip = $(this.options.template)
    return this.$tip
  }
1787

1788

XhmikosR's avatar
XhmikosR committed
1789
1790
  // POPOVER PLUGIN DEFINITION
  // =========================
1791

XhmikosR's avatar
XhmikosR committed
1792
1793
  function Plugin(option) {
    return this.each(function () {
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1794
1795
1796
1797
      var $this    = $(this)
      var data     = $this.data('bs.popover')
      var options  = typeof option == 'object' && option
      var selector = options && options.selector
Chris Rebert's avatar
Chris Rebert committed
1798

XhmikosR's avatar
XhmikosR committed
1799
      if (!data && option == 'destroy') return
Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1800
1801
1802
1803
1804
1805
      if (selector) {
        if (!data) $this.data('bs.popover', (data = {}))
        if (!data[selector]) data[selector] = new Popover(this, options)
      } else {
        if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
      }
XhmikosR's avatar
XhmikosR committed
1806
1807
1808
      if (typeof option == 'string') data[option]()
    })
  }
1809

XhmikosR's avatar
XhmikosR committed
1810
  var old = $.fn.popover
Mark Otto's avatar
Mark Otto committed
1811

XhmikosR's avatar
XhmikosR committed
1812
1813
  $.fn.popover             = Plugin
  $.fn.popover.Constructor = Popover
fat's avatar
fat committed
1814

1815

XhmikosR's avatar
XhmikosR committed
1816
1817
  // POPOVER NO CONFLICT
  // ===================
1818

XhmikosR's avatar
XhmikosR committed
1819
1820
1821
1822
  $.fn.popover.noConflict = function () {
    $.fn.popover = old
    return this
  }
1823

XhmikosR's avatar
XhmikosR committed
1824
}(jQuery);
1825

1826
/* ========================================================================
Mark Otto's avatar
Mark Otto committed
1827
 * Bootstrap: scrollspy.js v3.3.1
Mark Otto's avatar
Mark Otto committed
1828
 * http://getbootstrap.com/javascript/#scrollspy
1829
 * ========================================================================
1830
 * Copyright 2011-2014 Twitter, Inc.
1831
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1832
 * ======================================================================== */
1833
1834


XhmikosR's avatar
XhmikosR committed
1835
1836
+function ($) {
  'use strict';
1837

XhmikosR's avatar
XhmikosR committed
1838
1839
  // SCROLLSPY CLASS DEFINITION
  // ==========================
1840

XhmikosR's avatar
XhmikosR committed
1841
1842
  function ScrollSpy(element, options) {
    var process  = $.proxy(this.process, this)
1843

XhmikosR's avatar
XhmikosR committed
1844
1845
1846
1847
1848
1849
1850
1851
    this.$body          = $('body')
    this.$scrollElement = $(element).is('body') ? $(window) : $(element)
    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
    this.selector       = (this.options.target || '') + ' .nav li > a'
    this.offsets        = []
    this.targets        = []
    this.activeTarget   = null
    this.scrollHeight   = 0
1852

XhmikosR's avatar
XhmikosR committed
1853
1854
1855
1856
    this.$scrollElement.on('scroll.bs.scrollspy', process)
    this.refresh()
    this.process()
  }
1857

Mark Otto's avatar
Mark Otto committed
1858
  ScrollSpy.VERSION  = '3.3.1'
Mark Otto's avatar
grunt    
Mark Otto committed
1859

XhmikosR's avatar
XhmikosR committed
1860
1861
1862
  ScrollSpy.DEFAULTS = {
    offset: 10
  }
1863

XhmikosR's avatar
XhmikosR committed
1864
1865
1866
  ScrollSpy.prototype.getScrollHeight = function () {
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  }
Mark Otto's avatar
grunt    
Mark Otto committed
1867

XhmikosR's avatar
XhmikosR committed
1868
1869
1870
  ScrollSpy.prototype.refresh = function () {
    var offsetMethod = 'offset'
    var offsetBase   = 0
Mark Otto's avatar
grunt    
Mark Otto committed
1871

XhmikosR's avatar
XhmikosR committed
1872
1873
1874
1875
    if (!$.isWindow(this.$scrollElement[0])) {
      offsetMethod = 'position'
      offsetBase   = this.$scrollElement.scrollTop()
    }
Mark Otto's avatar
grunt    
Mark Otto committed
1876

XhmikosR's avatar
XhmikosR committed
1877
1878
1879
    this.offsets = []
    this.targets = []
    this.scrollHeight = this.getScrollHeight()
fat's avatar
fat committed
1880

XhmikosR's avatar
XhmikosR committed
1881
    var self     = this
XhmikosR's avatar
XhmikosR committed
1882

XhmikosR's avatar
XhmikosR committed
1883
1884
1885
1886
1887
1888
    this.$body
      .find(this.selector)
      .map(function () {
        var $el   = $(this)
        var href  = $el.data('target') || $el.attr('href')
        var $href = /^#./.test(href) && $(href)
1889

XhmikosR's avatar
XhmikosR committed
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
        return ($href
          && $href.length
          && $href.is(':visible')
          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        self.offsets.push(this[0])
        self.targets.push(this[1])
      })
  }

  ScrollSpy.prototype.process = function () {
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
    var scrollHeight = this.getScrollHeight()
    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
    var offsets      = this.offsets
    var targets      = this.targets
    var activeTarget = this.activeTarget
    var i

    if (this.scrollHeight != scrollHeight) {
      this.refresh()
Mark Otto's avatar
grunt    
Mark Otto committed
1913
1914
    }

XhmikosR's avatar
XhmikosR committed
1915
1916
1917
    if (scrollTop >= maxScroll) {
      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
    }
1918

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1919
1920
1921
    if (activeTarget && scrollTop < offsets[0]) {
      this.activeTarget = null
      return this.clear()
Chris Rebert's avatar
Chris Rebert committed
1922
    }
1923

XhmikosR's avatar
XhmikosR committed
1924
1925
1926
1927
1928
1929
1930
    for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
        && this.activate(targets[i])
    }
  }
1931

XhmikosR's avatar
XhmikosR committed
1932
1933
  ScrollSpy.prototype.activate = function (target) {
    this.activeTarget = target
1934

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1935
    this.clear()
1936

XhmikosR's avatar
XhmikosR committed
1937
1938
1939
    var selector = this.selector +
        '[data-target="' + target + '"],' +
        this.selector + '[href="' + target + '"]'
1940

XhmikosR's avatar
XhmikosR committed
1941
1942
1943
    var active = $(selector)
      .parents('li')
      .addClass('active')
1944

XhmikosR's avatar
XhmikosR committed
1945
1946
1947
1948
    if (active.parent('.dropdown-menu').length) {
      active = active
        .closest('li.dropdown')
        .addClass('active')
Chris Rebert's avatar
Chris Rebert committed
1949
    }
1950

XhmikosR's avatar
XhmikosR committed
1951
1952
    active.trigger('activate.bs.scrollspy')
  }
1953

Heinrich Fenkart's avatar
grunt    
Heinrich Fenkart committed
1954
1955
1956
1957
1958
1959
  ScrollSpy.prototype.clear = function () {
    $(this.selector)
      .parentsUntil(this.options.target, '.active')
      .removeClass('active')
  }

1960

XhmikosR's avatar
XhmikosR committed
1961
1962
  // SCROLLSPY PLUGIN DEFINITION
  // ===========================
1963

XhmikosR's avatar
XhmikosR committed
1964
1965
1966
1967
1968
  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.scrollspy')
      var options = typeof option == 'object' && option
Mark Otto's avatar
Mark Otto committed
1969

XhmikosR's avatar
XhmikosR committed
1970
1971
1972
1973
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }
1974

XhmikosR's avatar
XhmikosR committed
1975
  var old = $.fn.scrollspy
1976

XhmikosR's avatar
XhmikosR committed
1977
1978
  $.fn.scrollspy             = Plugin
  $.fn.scrollspy.Constructor = ScrollSpy
1979

1980

XhmikosR's avatar
XhmikosR committed
1981
1982
  // SCROLLSPY NO CONFLICT
  // =====================
1983

XhmikosR's avatar
XhmikosR committed
1984
1985
1986
1987
  $.fn.scrollspy.noConflict = function () {
    $.fn.scrollspy = old
    return this
  }
1988

Chris Rebert's avatar
Chris Rebert committed
1989

XhmikosR's avatar
XhmikosR committed
1990
1991
  // SCROLLSPY DATA-API
  // ==================
Chris Rebert's avatar
Chris Rebert committed
1992

XhmikosR's avatar
XhmikosR committed
1993
1994
1995
1996
1997
  $(window).on('load.bs.scrollspy.data-api', function () {
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      Plugin.call($spy, $spy.data())
    })
1998
  })
1999

XhmikosR's avatar
XhmikosR committed
2000
}(jQuery);
For faster browsing, not all history is shown. View entire blame