bootstrap.js 56.9 KB
Newer Older
fat's avatar
fat committed
1001
      this.$backdrop.removeClass('in')
1002

fat's avatar
fat committed
1003
      $.support.transition && this.$element.hasClass('fade')?
1004
1005
1006
        this.$backdrop
          .one($.support.transition.end, callback)
          .emulateTransitionEnd(150) :
fat's avatar
fat committed
1007
        callback()
1008

fat's avatar
fat committed
1009
1010
1011
    } else if (callback) {
      callback()
    }
1012
1013
1014
  }


fat's avatar
fat committed
1015
1016
  // MODAL PLUGIN DEFINITION
  // =======================
1017

1018
1019
  var old = $.fn.modal

Jacob Thornton's avatar
Jacob Thornton committed
1020
  $.fn.modal = function (option, _relatedTarget) {
1021
    return this.each(function () {
fat's avatar
fat committed
1022
      var $this   = $(this)
Mark Otto's avatar
Mark Otto committed
1023
      var data    = $this.data('bs.modal')
fat's avatar
fat committed
1024
1025
      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)

Mark Otto's avatar
Mark Otto committed
1026
      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
Jacob Thornton's avatar
Jacob Thornton committed
1027
1028
      if (typeof option == 'string') data[option](_relatedTarget)
      else if (options.show) data.show(_relatedTarget)
1029
1030
1031
1032
1033
1034
    })
  }

  $.fn.modal.Constructor = Modal


fat's avatar
fat committed
1035
1036
  // MODAL NO CONFLICT
  // =================
1037
1038
1039
1040
1041
1042
1043

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


fat's avatar
fat committed
1044
1045
  // MODAL DATA-API
  // ==============
1046

Mark Otto's avatar
Mark Otto committed
1047
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
fat's avatar
fat committed
1048
1049
1050
    var $this   = $(this)
    var href    = $this.attr('href')
    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
Jacob Thornton's avatar
Jacob Thornton committed
1051
    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1052

1053
    e.preventDefault()
1054

1055
    $target
Jacob Thornton's avatar
Jacob Thornton committed
1056
      .modal(option, this)
1057
      .one('hide', function () {
1058
        $this.is(':visible') && $this.focus()
1059
      })
Jacob Thornton's avatar
Jacob Thornton committed
1060
  })
1061

Jacob Thornton's avatar
Jacob Thornton committed
1062
1063
1064
  $(document)
    .on('shown.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })
    .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
1065

1066
}(window.jQuery);
1067

1068
/* ========================================================================
1069
1070
1071
 * Bootstrap: tooltip.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#affix
 * Inspired by the original jQuery.tipsy by Jason Frame
1072
 * ========================================================================
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
1086
 * ======================================================================== */
1087
1088


1089
+function ($) { "use strict";
1090

1091
  // TOOLTIP PUBLIC CLASS DEFINITION
fat's avatar
fat committed
1092
  // ===============================
1093

1094
1095
1096
1097
1098
1099
1100
  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null
1101

1102
1103
    this.init('tooltip', element, options)
  }
1104

1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
  Tooltip.DEFAULTS = {
    animation: true
  , placement: 'top'
  , selector: false
  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
  , trigger: 'hover focus'
  , title: ''
  , delay: 0
  , html: false
  , container: false
  }
1116

1117
1118
1119
1120
1121
  Tooltip.prototype.init = function (type, element, options) {
    this.enabled  = true
    this.type     = type
    this.$element = $(element)
    this.options  = this.getOptions(options)
1122

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

1125
1126
    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]
fat's avatar
fat committed
1127

1128
1129
1130
1131
1132
      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' : 'focus'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
1133

Jacob Thornton's avatar
Jacob Thornton committed
1134
        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1135
1136
1137
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }
1138

1139
1140
1141
    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
fat's avatar
fat committed
1142
  }
1143

1144
1145
  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
1146
  }
1147

1148
1149
  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1150

1151
1152
1153
1154
1155
1156
    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay
      , hide: options.delay
      }
    }
1157

1158
    return options
1159
  }
Jacob Thornton's avatar
Jacob Thornton committed
1160

Jacob Thornton's avatar
Jacob Thornton committed
1161
  Tooltip.prototype.getDelegateOptions = function () {
1162
    var options  = {}
Jacob Thornton's avatar
Jacob Thornton committed
1163
    var defaults = this.getDefaults()
1164

1165
1166
1167
    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })
fat's avatar
rebuild    
fat committed
1168

Jacob Thornton's avatar
Jacob Thornton committed
1169
1170
1171
1172
    return options
  }

  Tooltip.prototype.enter = function (obj) {
1173
    var self = obj instanceof this.constructor ?
Jacob Thornton's avatar
Jacob Thornton committed
1174
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
1175

1176
    clearTimeout(self.timeout)
1177

1178
    if (!self.options.delay || !self.options.delay.show) return self.show()
1179

1180
1181
1182
1183
    self.hoverState = 'in'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
1184
  }
1185

1186
1187
  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
Jacob Thornton's avatar
Jacob Thornton committed
1188
      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
1189

1190
    clearTimeout(self.timeout)
fat's avatar
fat committed
1191

1192
    if (!self.options.delay || !self.options.delay.hide) return self.hide()
1193

1194
1195
1196
1197
    self.hoverState = 'out'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
1198
  }
1199

1200
1201
  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.'+ this.type)
1202

1203
1204
    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)
1205

1206
      if (e.isDefaultPrevented()) return
1207

1208
      var $tip = this.tip()
fat's avatar
fat committed
1209

1210
      this.setContent()
fat's avatar
fat committed
1211

1212
      if (this.options.animation) $tip.addClass('fade')
fat's avatar
fat committed
1213

1214
1215
1216
      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement
1217

1218
1219
1220
      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1221

1222
1223
1224
1225
      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
1226

1227
      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1228

1229
1230
1231
      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight
fat's avatar
fat committed
1232

1233
1234
      if (autoPlace) {
        var $parent = this.$element.parent()
1235

1236
1237
1238
1239
1240
        var orgPlacement = placement
        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop
        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()
        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left
fat's avatar
fat committed
1241

1242
1243
1244
1245
1246
        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :
                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :
                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :
                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :
                    placement
fat's avatar
fat committed
1247

1248
1249
1250
1251
1252
        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

1253
      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1254

fat's avatar
fat committed
1255
      this.applyPlacement(calculatedOffset, placement)
1256
      this.$element.trigger('shown.bs.' + this.type)
fat's avatar
fat committed
1257
    }
1258
  }
fat's avatar
fat committed
1259

1260
1261
1262
1263
1264
  Tooltip.prototype.applyPlacement = function(offset, placement) {
    var replace
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight
fat's avatar
fat committed
1265

1266
    // manually read margins because getBoundingClientRect includes difference
fat's avatar
fat committed
1267
1268
1269
1270
1271
1272
1273
1274
1275
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  = offset.top  + marginTop
    offset.left = offset.left + marginLeft
fat's avatar
fat committed
1276

1277
1278
1279
    $tip
      .offset(offset)
      .addClass('in')
fat's avatar
fat committed
1280

fat's avatar
fat committed
1281
    // check to see if placing tip in new offset caused the tip to resize itself
1282
1283
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight
fat's avatar
fat committed
1284

1285
1286
    if (placement == 'top' && actualHeight != height) {
      replace = true
fat's avatar
fat committed
1287
      offset.top = offset.top + height - actualHeight
fat's avatar
fat committed
1288
1289
    }

fat's avatar
fat committed
1290
    if (/bottom|top/.test(placement)) {
1291
      var delta = 0
1292

fat's avatar
fat committed
1293
      if (offset.left < 0) {
1294
1295
        delta       = offset.left * -2
        offset.left = 0
fat's avatar
fat committed
1296

1297
        $tip.offset(offset)
1298

1299
1300
1301
        actualWidth  = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight
      }
1302

1303
1304
1305
1306
      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
    } else {
      this.replaceArrow(actualHeight - height, actualHeight, 'top')
    }
1307

1308
    if (replace) $tip.offset(offset)
1309
  }
1310

1311
1312
  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
fat's avatar
fat committed
1313
  }
1314

1315
1316
1317
  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()
1318

1319
1320
1321
    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }
1322

1323
1324
1325
1326
  Tooltip.prototype.hide = function () {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)
1327

Jacob Thornton's avatar
Jacob Thornton committed
1328
1329
    function complete() { $tip.detach() }

1330
    this.$element.trigger(e)
1331

1332
    if (e.isDefaultPrevented()) return
1333

1334
    $tip.removeClass('in')
1335

1336
1337
    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
Jacob Thornton's avatar
Jacob Thornton committed
1338
        .one($.support.transition.end, complete)
1339
        .emulateTransitionEnd(150) :
Jacob Thornton's avatar
Jacob Thornton committed
1340
      complete()
1341

1342
    this.$element.trigger('hidden.bs.' + this.type)
1343

1344
    return this
1345
1346
  }

1347
1348
1349
1350
  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', '')
1351
    }
1352
  }
1353

1354
1355
1356
  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }
1357

1358
1359
1360
1361
1362
1363
1364
  Tooltip.prototype.getPosition = function () {
    var el = this.$element[0]
    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
      width: el.offsetWidth
    , height: el.offsetHeight
    }, this.$element.offset())
  }
1365

1366
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
fat's avatar
fat committed
1367
1368
1369
1370
1371
1372
    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   }
  }

1373
1374
1375
1376
  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options
1377

1378
1379
    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
1380

1381
    return title
1382
  }
1383

1384
1385
1386
  Tooltip.prototype.tip = function () {
    return this.$tip = this.$tip || $(this.options.template)
  }
1387

Mark Otto's avatar
Mark Otto committed
1388
  Tooltip.prototype.arrow = function () {
fat's avatar
fat committed
1389
    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
1390
  }
1391

1392
1393
1394
1395
1396
1397
1398
  Tooltip.prototype.validate = function () {
    if (!this.$element[0].parentNode) {
      this.hide()
      this.$element = null
      this.options  = null
    }
  }
1399

1400
1401
1402
  Tooltip.prototype.enable = function () {
    this.enabled = true
  }
1403

1404
1405
1406
  Tooltip.prototype.disable = function () {
    this.enabled = false
  }
1407

1408
1409
1410
  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }
Mark Otto's avatar
Mark Otto committed
1411

1412
  Tooltip.prototype.toggle = function (e) {
Jacob Thornton's avatar
Jacob Thornton committed
1413
    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
1414
1415
    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }
1416

1417
1418
  Tooltip.prototype.destroy = function () {
    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
fat's avatar
fat committed
1419
  }
1420
1421


1422
1423
  // TOOLTIP PLUGIN DEFINITION
  // =========================
1424

1425
  var old = $.fn.tooltip
1426

1427
  $.fn.tooltip = function (option) {
1428
    return this.each(function () {
1429
1430
1431
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option
fat's avatar
fat committed
1432

1433
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1434
1435
1436
1437
      if (typeof option == 'string') data[option]()
    })
  }

1438
  $.fn.tooltip.Constructor = Tooltip
1439

1440

1441
1442
  // TOOLTIP NO CONFLICT
  // ===================
1443

1444
1445
  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
1446
1447
1448
    return this
  }

Mark Otto's avatar
Mark Otto committed
1449
}(window.jQuery);
1450

1451
/* ========================================================================
1452
1453
 * Bootstrap: popover.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#popovers
1454
 * ========================================================================
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
1468
 * ======================================================================== */
1469
1470


1471
+function ($) { "use strict";
1472

1473
  // POPOVER PUBLIC CLASS DEFINITION
1474
  // ===============================
fat's avatar
fat committed
1475

1476
1477
  var Popover = function (element, options) {
    this.init('popover', element, options)
1478
1479
  }

fat's avatar
fat committed
1480
1481
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')

1482
1483
1484
1485
1486
1487
  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
    placement: 'right'
  , trigger: 'click'
  , content: ''
  , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  })
1488

fat's avatar
fat committed
1489

1490
1491
  // NOTE: POPOVER EXTENDS tooltip.js
  // ================================
fat's avatar
fat committed
1492

1493
  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1494

1495
  Popover.prototype.constructor = Popover
fat's avatar
fat committed
1496

1497
1498
1499
  Popover.prototype.getDefaults = function () {
    return Popover.DEFAULTS
  }
1500

1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
  Popover.prototype.setContent = function () {
    var $tip    = this.tip()
    var title   = this.getTitle()
    var content = this.getContent()

    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)

    $tip.removeClass('fade top bottom left right in')

1511
1512
    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
    // this manually by checking the contents.
Jacob Thornton's avatar
Jacob Thornton committed
1513
    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1514
1515
  }

1516
1517
  Popover.prototype.hasContent = function () {
    return this.getTitle() || this.getContent()
1518
1519
  }

1520
1521
1522
  Popover.prototype.getContent = function () {
    var $e = this.$element
    var o  = this.options
1523

1524
1525
1526
1527
1528
    return $e.attr('data-content')
      || (typeof o.content == 'function' ?
            o.content.call($e[0]) :
            o.content)
  }
1529

Mark Otto's avatar
Mark Otto committed
1530
  Popover.prototype.arrow = function () {
fat's avatar
fat committed
1531
1532
1533
    return this.$arrow = this.$arrow || this.tip().find('.arrow')
  }

1534
1535
1536
  Popover.prototype.tip = function () {
    if (!this.$tip) this.$tip = $(this.options.template)
    return this.$tip
fat's avatar
fat committed
1537
  }
1538

1539

1540
1541
  // POPOVER PLUGIN DEFINITION
  // =========================
1542

1543
  var old = $.fn.popover
1544

1545
1546
1547
1548
1549
  $.fn.popover = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.popover')
      var options = typeof option == 'object' && option
1550

1551
1552
1553
      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
      if (typeof option == 'string') data[option]()
    })
1554
1555
  }

1556
  $.fn.popover.Constructor = Popover
fat's avatar
fat committed
1557

1558

1559
1560
  // POPOVER NO CONFLICT
  // ===================
1561

1562
1563
1564
1565
  $.fn.popover.noConflict = function () {
    $.fn.popover = old
    return this
  }
1566

1567
}(window.jQuery);
1568

1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
/* ========================================================================
 * Bootstrap: scrollspy.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#scrollspy
 * ========================================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================================== */
1587
1588


1589
+function ($) { "use strict";
1590

1591
1592
  // SCROLLSPY CLASS DEFINITION
  // ==========================
1593

1594
1595
1596
  function ScrollSpy(element, options) {
    var href
    var process  = $.proxy(this.process, this)
1597

fat's avatar
fat committed
1598
    this.$element       = $(element).is('body') ? $(window) : $(element)
1599
    this.$body          = $('body')
fat's avatar
fat committed
1600
    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)
1601
1602
1603
1604
1605
1606
1607
    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
    this.selector       = (this.options.target
      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
      || '') + ' .nav li > a'
    this.offsets        = $([])
    this.targets        = $([])
    this.activeTarget   = null
1608

1609
1610
1611
    this.refresh()
    this.process()
  }
1612

1613
1614
1615
  ScrollSpy.DEFAULTS = {
    offset: 10
  }
1616

1617
  ScrollSpy.prototype.refresh = function () {
fat's avatar
fat committed
1618
1619
    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'

1620
1621
    this.offsets = $([])
    this.targets = $([])
1622

1623
1624
1625
1626
1627
1628
1629
    var self     = this
    var $targets = this.$body
      .find(this.selector)
      .map(function () {
        var $el   = $(this)
        var href  = $el.data('target') || $el.attr('href')
        var $href = /^#\w/.test(href) && $(href)
1630

1631
1632
        return ($href
          && $href.length
fat's avatar
fat committed
1633
          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
1634
1635
1636
1637
1638
1639
1640
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        self.offsets.push(this[0])
        self.targets.push(this[1])
      })
  }
1641

1642
1643
1644
1645
1646
1647
1648
1649
  ScrollSpy.prototype.process = function () {
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
    var maxScroll    = scrollHeight - this.$scrollElement.height()
    var offsets      = this.offsets
    var targets      = this.targets
    var activeTarget = this.activeTarget
    var i
1650

1651
1652
1653
    if (scrollTop >= maxScroll) {
      return activeTarget != (i = targets.last()[0]) && this.activate(i)
    }
1654

1655
1656
1657
1658
1659
    for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
        && this.activate( targets[i] )
1660
    }
1661
1662
  }

1663
1664
  ScrollSpy.prototype.activate = function (target) {
    this.activeTarget = target
1665

1666
1667
1668
    $(this.selector)
      .parents('.active')
      .removeClass('active')
1669

1670
1671
1672
    var selector = this.selector
      + '[data-target="' + target + '"],'
      + this.selector + '[href="' + target + '"]'
1673

1674
1675
1676
    var active = $(selector)
      .parents('li')
      .addClass('active')
1677

1678
1679
1680
1681
    if (active.parent('.dropdown-menu').length)  {
      active = active
        .closest('li.dropdown')
        .addClass('active')
1682
    }
1683

1684
1685
    active.trigger('activate')
  }
1686
1687


1688
1689
  // SCROLLSPY PLUGIN DEFINITION
  // ===========================
1690

1691
  var old = $.fn.scrollspy
1692

1693
1694
1695
1696
1697
  $.fn.scrollspy = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.scrollspy')
      var options = typeof option == 'object' && option
1698

1699
1700
1701
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
      if (typeof option == 'string') data[option]()
    })
1702
1703
  }

1704
  $.fn.scrollspy.Constructor = ScrollSpy
1705
1706


1707
1708
1709
1710
1711
1712
  // SCROLLSPY NO CONFLICT
  // =====================

  $.fn.scrollspy.noConflict = function () {
    $.fn.scrollspy = old
    return this
1713
1714
1715
  }


1716
1717
  // SCROLLSPY DATA-API
  // ==================
1718

1719
1720
1721
1722
1723
1724
  $(window).on('load', function () {
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      $spy.scrollspy($spy.data())
    })
  })
1725

1726
}(window.jQuery);
1727

1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
/* ========================================================================
 * Bootstrap: tab.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#tabs
 * ========================================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ======================================================================== */
1746

1747

1748
1749
1750
1751
1752
1753
1754
+function ($) { "use strict";

  // TAB CLASS DEFINITION
  // ====================

  var Tab = function (element) {
    this.element = $(element)
1755
  }
1756

1757
1758
1759
1760
1761
1762
1763
1764
  Tab.prototype.show = function () {
    var $this    = this.element
    var $ul      = $this.closest('ul:not(.dropdown-menu)')
    var selector = $this.attr('data-target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
1765
    }
1766

1767
    if ($this.parent('li').hasClass('active')) return
1768

1769
1770
1771
1772
    var previous = $ul.find('.active:last a')[0]
    var e        = $.Event('show.bs.tab', {
      relatedTarget: previous
    })
1773

1774
    $this.trigger(e)
1775

1776
    if (e.isDefaultPrevented()) return
1777

1778
    var $target = $(selector)
1779

1780
1781
1782
1783
1784
1785
1786
    this.activate($this.parent('li'), $ul)
    this.activate($target, $target.parent(), function () {
      $this.trigger({
        type: 'shown.bs.tab'
      , relatedTarget: previous
      })
    })
1787
  }
1788

1789
1790
1791
1792
1793
  Tab.prototype.activate = function (element, container, callback) {
    var $active    = container.find('> .active')
    var transition = callback
      && $.support.transition
      && $active.hasClass('fade')
1794

1795
1796
1797
1798
1799
    function next() {
      $active
        .removeClass('active')
        .find('> .dropdown-menu > .active')
        .removeClass('active')
1800

1801
      element.addClass('active')
1802

1803
1804
1805
1806
1807
1808
      if (transition) {
        element[0].offsetWidth // reflow for transition
        element.addClass('in')
      } else {
        element.removeClass('fade')
      }
1809

1810
1811
1812
      if (element.parent('.dropdown-menu')) {
        element.closest('li.dropdown').addClass('active')
      }
fat's avatar
fat committed
1813

1814
1815
      callback && callback()
    }
fat's avatar
fat committed
1816

1817
1818
1819
1820
1821
1822
1823
    transition ?
      $active
        .one($.support.transition.end, next)
        .emulateTransitionEnd(150) :
      next()

    $active.removeClass('in')
1824
1825
1826
  }


1827
1828
  // TAB PLUGIN DEFINITION
  // =====================
1829

1830
  var old = $.fn.tab
1831

1832
  $.fn.tab = function ( option ) {
1833
    return this.each(function () {
1834
1835
      var $this = $(this)
      var data  = $this.data('bs.tab')
fat's avatar
fat committed
1836

1837
      if (!data) $this.data('bs.tab', (data = new Tab(this)))
1838
1839
1840
1841
      if (typeof option == 'string') data[option]()
    })
  }

1842
  $.fn.tab.Constructor = Tab
1843
1844


1845
1846
  // TAB NO CONFLICT
  // ===============
1847

1848
1849
  $.fn.tab.noConflict = function () {
    $.fn.tab = old
1850
1851
1852
    return this
  }

1853
1854
1855
1856
1857
1858
1859
1860
1861

  // TAB DATA-API
  // ============

  $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
    e.preventDefault()
    $(this).tab('show')
  })

1862
}(window.jQuery);
1863

1864
/* ========================================================================
1865
1866
 * Bootstrap: affix.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#affix
1867
 * ========================================================================
1868
 * Copyright 2012 Twitter, Inc.
Mark Otto's avatar
Mark Otto committed
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
1881
 * ======================================================================== */
Mark Otto's avatar
Mark Otto committed
1882
1883


1884
+function ($) { "use strict";
Mark Otto's avatar
Mark Otto committed
1885

1886
1887
  // AFFIX CLASS DEFINITION
  // ======================
Mark Otto's avatar
Mark Otto committed
1888

1889
1890
1891
1892
1893
  var Affix = function (element, options) {
    this.options = $.extend({}, Affix.DEFAULTS, options)
    this.$window = $(window)
      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
fat's avatar
fat committed
1894

1895
1896
1897
    this.$element = $(element)
    this.affixed  =
    this.unpin    = null
fat's avatar
fat committed
1898

1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
    this.checkPosition()
  }

  Affix.RESET = 'affix affix-top affix-bottom'

  Affix.DEFAULTS = {
    offset: 0
  }

  Affix.prototype.checkPositionWithEventLoop = function () {
    setTimeout($.proxy(this.checkPosition, this), 1)
  }

  Affix.prototype.checkPosition = function () {
    if (!this.$element.is(':visible')) return

    var scrollHeight = $(document).height()
    var scrollTop    = this.$window.scrollTop()
    var position     = this.$element.offset()
    var offset       = this.options.offset
    var offsetTop    = offset.top
    var offsetBottom = offset.bottom

    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
    if (typeof offsetTop == 'function')    offsetTop    = offset.top()
    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()

    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false

    if (this.affixed === affix) return
    if (this.unpin) this.$element.css('top', '')

    this.affixed = affix
    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null

    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))

    if (affix == 'bottom') {
      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
1940
    }
Mark Otto's avatar
Mark Otto committed
1941
1942
  }

1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957

  // AFFIX PLUGIN DEFINITION
  // =======================

  var old = $.fn.affix

  $.fn.affix = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.affix')
      var options = typeof option == 'object' && option

      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
      if (typeof option == 'string') data[option]()
    })
1958
1959
  }

1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
  $.fn.affix.Constructor = Affix


  // AFFIX NO CONFLICT
  // =================

  $.fn.affix.noConflict = function () {
    $.fn.affix = old
    return this
  }


  // AFFIX DATA-API
  // ==============

  $(window).on('load', function () {
    $('[data-spy="affix"]').each(function () {
      var $spy = $(this)
      var data = $spy.data()

      data.offset = data.offset || {}

      if (data.offsetBottom) data.offset.bottom = data.offsetBottom
      if (data.offsetTop)    data.offset.top    = data.offsetTop

      $spy.affix(data)
    })
Mark Otto's avatar
Mark Otto committed
1987
1988
  })

1989
}(window.jQuery);
For faster browsing, not all history is shown. View entire blame