bootstrap.js 55.8 KB
Newer Older
1
2
3
4
5
/**
* bootstrap.js v3.0.0 by @fat and @mdo
* Copyright 2013 Twitter Inc.
* http://www.apache.org/licenses/LICENSE-2.0
*/
6
7
if (!jQuery) { throw new Error("Bootstrap requires jQuery") }

8
/* ========================================================================
9
10
 * Bootstrap: transition.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#transitions
11
 * ========================================================================
12
 * Copyright 2013 Twitter, Inc.
13
14
15
16
17
18
19
20
21
22
23
24
 *
 * 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.
25
 * ======================================================================== */
26
27


28
+function ($) { "use strict";
29

30
31
  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================
32

33
34
  function transitionEnd() {
    var el = document.createElement('bootstrap')
35

36
37
38
39
40
    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd'
    , 'MozTransition'    : 'transitionend'
    , 'OTransition'      : 'oTransitionEnd otransitionend'
    , 'transition'       : 'transitionend'
fat's avatar
fat committed
41
    }
42

43
44
45
46
47
    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }
48
49
  }

50
51
52
  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el    = this
liuyl's avatar
liuyl committed
53
54
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
55
    setTimeout(callback, duration)
56
    return this
57
58
  }

59
60
  $(function () {
    $.support.transition = transitionEnd()
fat's avatar
fat committed
61
  })
62

Mark Otto's avatar
Mark Otto committed
63
}(window.jQuery);
64

65
/* ========================================================================
fat's avatar
fat committed
66
 * Bootstrap: alert.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
67
 * http://twbs.github.com/bootstrap/javascript.html#alerts
68
 * ========================================================================
fat's avatar
fat committed
69
 * Copyright 2013 Twitter, Inc.
70
71
72
73
74
75
76
77
78
79
80
81
 *
 * 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.
82
 * ======================================================================== */
83
84


85
+function ($) { "use strict";
86

fat's avatar
fat committed
87
88
  // ALERT CLASS DEFINITION
  // ======================
89
90

  var dismiss = '[data-dismiss="alert"]'
fat's avatar
fat committed
91
92
93
  var Alert   = function (el) {
    $(el).on('click', dismiss, this.close)
  }
94
95

  Alert.prototype.close = function (e) {
fat's avatar
fat committed
96
97
    var $this    = $(this)
    var selector = $this.attr('data-target')
98
99
100

    if (!selector) {
      selector = $this.attr('href')
fat's avatar
fat committed
101
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
102
103
    }

fat's avatar
fat committed
104
    var $parent = $(selector)
105

fat's avatar
fat committed
106
    if (e) e.preventDefault()
107

fat's avatar
fat committed
108
109
110
    if (!$parent.length) {
      $parent = $this.hasClass('alert') ? $this : $this.parent()
    }
111

Mark Otto's avatar
Mark Otto committed
112
    $parent.trigger(e = $.Event('close.bs.alert'))
113
114
115
116
117
118

    if (e.isDefaultPrevented()) return

    $parent.removeClass('in')

    function removeElement() {
Mark Otto's avatar
Mark Otto committed
119
      $parent.trigger('closed.bs.alert').remove()
120
121
122
    }

    $.support.transition && $parent.hasClass('fade') ?
123
124
125
      $parent
        .one($.support.transition.end, removeElement)
        .emulateTransitionEnd(150) :
126
127
128
129
      removeElement()
  }


fat's avatar
fat committed
130
131
  // ALERT PLUGIN DEFINITION
  // =======================
132

133
134
  var old = $.fn.alert

135
136
137
  $.fn.alert = function (option) {
    return this.each(function () {
      var $this = $(this)
Mark Otto's avatar
Mark Otto committed
138
      var data  = $this.data('bs.alert')
fat's avatar
fat committed
139

Mark Otto's avatar
Mark Otto committed
140
      if (!data) $this.data('bs.alert', (data = new Alert(this)))
141
142
143
144
145
146
147
      if (typeof option == 'string') data[option].call($this)
    })
  }

  $.fn.alert.Constructor = Alert


fat's avatar
fat committed
148
149
  // ALERT NO CONFLICT
  // =================
150
151
152
153
154
155
156

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


fat's avatar
fat committed
157
  // ALERT DATA-API
fat's avatar
fat committed
158
  // ==============
159

Mark Otto's avatar
Mark Otto committed
160
  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
161

Mark Otto's avatar
Mark Otto committed
162
}(window.jQuery);
163

164
/* ========================================================================
fat's avatar
fat committed
165
 * Bootstrap: button.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
166
 * http://twbs.github.com/bootstrap/javascript.html#buttons
167
 * ========================================================================
fat's avatar
fat committed
168
 * Copyright 2013 Twitter, Inc.
169
170
171
172
173
174
175
176
177
178
179
180
 *
 * 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.
181
 * ======================================================================== */
182
183


184
+function ($) { "use strict";
185

fat's avatar
fat committed
186
187
  // BUTTON PUBLIC CLASS DEFINITION
  // ==============================
188
189
190

  var Button = function (element, options) {
    this.$element = $(element)
fat's avatar
fat committed
191
192
193
194
195
    this.options  = $.extend({}, Button.DEFAULTS, options)
  }

  Button.DEFAULTS = {
    loadingText: 'loading...'
196
197
198
  }

  Button.prototype.setState = function (state) {
fat's avatar
fat committed
199
200
201
202
    var d    = 'disabled'
    var $el  = this.$element
    var val  = $el.is('input') ? 'val' : 'html'
    var data = $el.data()
203
204

    state = state + 'Text'
fat's avatar
fat committed
205
206

    if (!data.resetText) $el.data('resetText', $el[val]())
207
208
209
210
211
212
213

    $el[val](data[state] || this.options[state])

    // push to event loop to allow forms to submit
    setTimeout(function () {
      state == 'loadingText' ?
        $el.addClass(d).attr(d, d) :
fat's avatar
fat committed
214
        $el.removeClass(d).removeAttr(d);
215
216
217
218
    }, 0)
  }

  Button.prototype.toggle = function () {
219
    var $parent = this.$element.closest('[data-toggle="buttons"]')
220

221
222
223
    if ($parent.length) {
      var $input = this.$element.find('input').prop('checked', !this.$element.hasClass('active'))
      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
fat's avatar
fat committed
224
    }
225
226
227
228
229

    this.$element.toggleClass('active')
  }


fat's avatar
fat committed
230
231
  // BUTTON PLUGIN DEFINITION
  // ========================
232

233
234
  var old = $.fn.button

235
236
  $.fn.button = function (option) {
    return this.each(function () {
fat's avatar
fat committed
237
      var $this   = $(this)
fat's avatar
fat committed
238
      var data    = $this.data('bs.button')
fat's avatar
fat committed
239
240
      var options = typeof option == 'object' && option

Mark Otto's avatar
Mark Otto committed
241
      if (!data) $this.data('bs.button', (data = new Button(this, options)))
fat's avatar
fat committed
242

243
244
245
246
247
248
249
250
      if (option == 'toggle') data.toggle()
      else if (option) data.setState(option)
    })
  }

  $.fn.button.Constructor = Button


fat's avatar
fat committed
251
252
  // BUTTON NO CONFLICT
  // ==================
253
254
255
256
257
258
259

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


fat's avatar
fat committed
260
261
  // BUTTON DATA-API
  // ===============
262

Mark Otto's avatar
Mark Otto committed
263
  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
264
265
266
    var $btn = $(e.target)
    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
    $btn.button('toggle')
267
    e.preventDefault()
268
269
  })

Mark Otto's avatar
Mark Otto committed
270
}(window.jQuery);
271

272
/* ========================================================================
fat's avatar
fat committed
273
 * Bootstrap: carousel.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
274
 * http://twbs.github.com/bootstrap/javascript.html#carousel
275
 * ========================================================================
276
277
278
279
280
281
282
283
284
285
286
287
288
 * 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.
289
 * ======================================================================== */
290
291


292
+function ($) { "use strict";
293

fat's avatar
fat committed
294
295
  // CAROUSEL CLASS DEFINITION
  // =========================
296
297

  var Carousel = function (element, options) {
fat's avatar
fat committed
298
    this.$element    = $(element)
fat's avatar
fat committed
299
    this.$indicators = this.$element.find('.carousel-indicators')
fat's avatar
fat committed
300
301
302
303
304
305
306
    this.options     = options
    this.paused      =
    this.sliding     =
    this.interval    =
    this.$active     =
    this.$items      = null

307
308
309
310
311
    this.options.pause == 'hover' && this.$element
      .on('mouseenter', $.proxy(this.pause, this))
      .on('mouseleave', $.proxy(this.cycle, this))
  }

fat's avatar
fat committed
312
313
314
315
  Carousel.DEFAULTS = {
    interval: 5000
  , pause: 'hover'
  }
316

fat's avatar
fat committed
317
318
  Carousel.prototype.cycle =  function (e) {
    e || (this.paused = false)
319

fat's avatar
fat committed
320
    this.interval && clearInterval(this.interval)
fat's avatar
fat committed
321

fat's avatar
fat committed
322
323
324
    this.options.interval
      && !this.paused
      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
325

fat's avatar
fat committed
326
327
    return this
  }
328

fat's avatar
fat committed
329
330
331
  Carousel.prototype.getActiveIndex = function () {
    this.$active = this.$element.find('.item.active')
    this.$items  = this.$active.parent().children()
332

fat's avatar
fat committed
333
334
    return this.$items.index(this.$active)
  }
335

fat's avatar
fat committed
336
337
338
  Carousel.prototype.to = function (pos) {
    var that        = this
    var activeIndex = this.getActiveIndex()
339

fat's avatar
fat committed
340
    if (pos > (this.$items.length - 1) || pos < 0) return
341

fat's avatar
fat committed
342
343
344
345
346
    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })
    if (activeIndex == pos) return this.pause().cycle()

    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
  }
347

fat's avatar
fat committed
348
349
350
351
352
353
  Carousel.prototype.pause = function (e) {
    e || (this.paused = true)

    if (this.$element.find('.next, .prev').length && $.support.transition.end) {
      this.$element.trigger($.support.transition.end)
      this.cycle(true)
354
355
    }

fat's avatar
fat committed
356
    this.interval = clearInterval(this.interval)
357

fat's avatar
fat committed
358
359
    return this
  }
360

fat's avatar
fat committed
361
362
363
364
  Carousel.prototype.next = function () {
    if (this.sliding) return
    return this.slide('next')
  }
365

fat's avatar
fat committed
366
367
368
369
  Carousel.prototype.prev = function () {
    if (this.sliding) return
    return this.slide('prev')
  }
370

fat's avatar
fat committed
371
372
373
374
375
376
377
  Carousel.prototype.slide = function (type, next) {
    var $active   = this.$element.find('.item.active')
    var $next     = next || $active[type]()
    var isCycling = this.interval
    var direction = type == 'next' ? 'left' : 'right'
    var fallback  = type == 'next' ? 'first' : 'last'
    var that      = this
Jacob Thornton's avatar
Jacob Thornton committed
378

fat's avatar
fat committed
379
    this.sliding = true
380

fat's avatar
fat committed
381
    isCycling && this.pause()
fat's avatar
fat committed
382

fat's avatar
fat committed
383
    $next = $next.length ? $next : this.$element.find('.item')[fallback]()
384

Mark Otto's avatar
Mark Otto committed
385
    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
386

fat's avatar
fat committed
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
    if ($next.hasClass('active')) return

    if (this.$indicators.length) {
      this.$indicators.find('.active').removeClass('active')
      this.$element.one('slid', function () {
        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
        $nextIndicator && $nextIndicator.addClass('active')
      })
    }

    if ($.support.transition && this.$element.hasClass('slide')) {
      this.$element.trigger(e)
      if (e.isDefaultPrevented()) return
      $next.addClass(type)
      $next[0].offsetWidth // force reflow
      $active.addClass(direction)
      $next.addClass(direction)
Jacob Thornton's avatar
Jacob Thornton committed
404
      $active
405
406
407
408
409
410
411
        .one($.support.transition.end, function () {
          $next.removeClass([type, direction].join(' ')).addClass('active')
          $active.removeClass(['active', direction].join(' '))
          that.sliding = false
          setTimeout(function () { that.$element.trigger('slid') }, 0)
        })
        .emulateTransitionEnd(600)
fat's avatar
fat committed
412
413
414
415
416
417
418
    } else {
      this.$element.trigger(e)
      if (e.isDefaultPrevented()) return
      $active.removeClass('active')
      $next.addClass('active')
      this.sliding = false
      this.$element.trigger('slid')
419
420
    }

fat's avatar
fat committed
421
422
423
    isCycling && this.cycle()

    return this
424
425
426
  }


fat's avatar
fat committed
427
428
  // CAROUSEL PLUGIN DEFINITION
  // ==========================
429

430
431
  var old = $.fn.carousel

432
433
  $.fn.carousel = function (option) {
    return this.each(function () {
fat's avatar
fat committed
434
      var $this   = $(this)
Mark Otto's avatar
Mark Otto committed
435
      var data    = $this.data('bs.carousel')
Jacob Thornton's avatar
Jacob Thornton committed
436
      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
fat's avatar
fat committed
437
438
      var action  = typeof option == 'string' ? option : options.slide

Mark Otto's avatar
Mark Otto committed
439
      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
440
      if (typeof option == 'number') data.to(option)
Jacob Thornton's avatar
Jacob Thornton committed
441
      else if (action) data[action]()
Mark Otto's avatar
Mark Otto committed
442
      else if (options.interval) data.pause().cycle()
443
444
445
446
447
448
    })
  }

  $.fn.carousel.Constructor = Carousel


fat's avatar
fat committed
449
450
  // CAROUSEL NO CONFLICT
  // ====================
451
452
453
454
455
456

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

fat's avatar
fat committed
457

fat's avatar
fat committed
458
459
  // CAROUSEL DATA-API
  // =================
460

461
  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
fat's avatar
fat committed
462
    var $this   = $(this), href
fat's avatar
fat committed
463
464
    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
    var options = $.extend({}, $target.data(), $this.data())
fat's avatar
fat committed
465
466
    var slideIndex = $this.attr('data-slide-to')
    if (slideIndex) options.interval = false
467

468
    $target.carousel(options)
469
470

    if (slideIndex = $this.attr('data-slide-to')) {
fat's avatar
fat committed
471
      $target.data('bs.carousel').to(slideIndex)
472
473
    }

474
    e.preventDefault()
475
476
  })

fat's avatar
fat committed
477
478
479
480
481
482
483
  $(window).on('load', function () {
    $('[data-ride="carousel"]').each(function () {
      var $carousel = $(this)
      $carousel.carousel($carousel.data())
    })
  })

Mark Otto's avatar
Mark Otto committed
484
}(window.jQuery);
485

486
/* ========================================================================
fat's avatar
fat committed
487
 * Bootstrap: collapse.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
488
 * http://twbs.github.com/bootstrap/javascript.html#collapse
489
 * ========================================================================
490
491
492
493
494
495
496
497
498
499
500
501
502
 * 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.
503
 * ======================================================================== */
504
505


506
+function ($) { "use strict";
507

508
509
  // COLLAPSE PUBLIC CLASS DEFINITION
  // ================================
510
511

  var Collapse = function (element, options) {
512
513
514
    this.$element      = $(element)
    this.options       = $.extend({}, Collapse.DEFAULTS, options)
    this.transitioning = null
515

516
517
518
519
520
521
522
    if (this.options.parent) this.$parent = $(this.options.parent)
    if (this.options.toggle) this.toggle()
  }

  Collapse.DEFAULTS = {
    toggle: true
  }
523

524
525
526
  Collapse.prototype.dimension = function () {
    var hasWidth = this.$element.hasClass('width')
    return hasWidth ? 'width' : 'height'
527
528
  }

529
530
  Collapse.prototype.show = function () {
    if (this.transitioning || this.$element.hasClass('in')) return
531

fat's avatar
fat committed
532
533
534
535
    var startEvent = $.Event('show.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

Mark Otto's avatar
Mark Otto committed
536
    var actives = this.$parent && this.$parent.find('> .accordion-group > .in')
537

538
    if (actives && actives.length) {
fat's avatar
fat committed
539
      var hasData = actives.data('bs.collapse')
540
541
      if (hasData && hasData.transitioning) return
      actives.collapse('hide')
fat's avatar
fat committed
542
      hasData || actives.data('bs.collapse', null)
543
544
    }

545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
    var dimension = this.dimension()

    this.$element
      .removeClass('collapse')
      .addClass('collapsing')
      [dimension](0)

    this.transitioning = 1

    var complete = function () {
      this.$element
        .removeClass('collapsing')
        .addClass('in')
        [dimension]('auto')
      this.transitioning = 0
      this.$element.trigger('shown.bs.collapse')
    }

    if (!$.support.transition) return complete.call(this)

    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
566

567
568
569
570
    this.$element
      .one($.support.transition.end, $.proxy(complete, this))
      .emulateTransitionEnd(350)
      [dimension](this.$element[0][scrollSize])
571
  }
572

573
574
  Collapse.prototype.hide = function () {
    if (this.transitioning || !this.$element.hasClass('in')) return
fat's avatar
fat committed
575
576
577
578
579

    var startEvent = $.Event('hide.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

580
    var dimension = this.dimension()
581

582
583
584
    this.$element
      [dimension](this.$element[dimension]())
      [0].offsetHeight
585

586
    this.$element
587
      .addClass('collapsing')
588
      .removeClass('collapse')
589
      .removeClass('in')
590

591
    this.transitioning = 1
592

593
    var complete = function () {
594
595
596
597
598
      this.transitioning = 0
      this.$element
        .trigger('hidden.bs.collapse')
        .removeClass('collapsing')
        .addClass('collapse')
599
600
    }

601
    if (!$.support.transition) return complete.call(this)
602

603
604
605
606
    this.$element
      [dimension](0)
      .one($.support.transition.end, $.proxy(complete, this))
      .emulateTransitionEnd(350)
607
  }
608

609
610
  Collapse.prototype.toggle = function () {
    this[this.$element.hasClass('in') ? 'hide' : 'show']()
611
612
613
  }


614
615
  // COLLAPSE PLUGIN DEFINITION
  // ==========================
616
617

  var old = $.fn.collapse
618
619
620

  $.fn.collapse = function (option) {
    return this.each(function () {
621
      var $this   = $(this)
fat's avatar
fat committed
622
      var data    = $this.data('bs.collapse')
623
624
      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)

fat's avatar
fat committed
625
      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
626
627
628
629
630
631
632
      if (typeof option == 'string') data[option]()
    })
  }

  $.fn.collapse.Constructor = Collapse


633
634
  // COLLAPSE NO CONFLICT
  // ====================
635

636
637
638
639
640
641
  $.fn.collapse.noConflict = function () {
    $.fn.collapse = old
    return this
  }


642
643
  // COLLAPSE DATA-API
  // =================
644

645
  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {
646
647
    var $this   = $(this), href
    var target  = $this.attr('data-target')
648
649
        || e.preventDefault()
        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
650
651
652
653
    var $target = $(target)
    var data    = $target.data('bs.collapse')
    var option  = data ? 'toggle' : $this.data()
    var parent  = $this.attr('data-parent')
Mark Otto's avatar
Mark Otto committed
654
    var $parent = parent && $(parent)
655

fat's avatar
fat committed
656
    if (!data || !data.transitioning) {
fat's avatar
fat committed
657
      if ($parent) $parent.find('[data-toggle=collapse][data-parent=' + parent + ']').not($this).addClass('collapsed')
658
      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
fat's avatar
fat committed
659
660
    }

661
    $target.collapse(option)
662
663
  })

Mark Otto's avatar
Mark Otto committed
664
}(window.jQuery);
665

666
/* ========================================================================
fat's avatar
fat committed
667
 * Bootstrap: dropdown.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
668
 * http://twbs.github.com/bootstrap/javascript.html#dropdowns
669
 * ========================================================================
670
671
672
673
674
675
676
677
678
679
680
681
682
 * 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.
683
 * ======================================================================== */
684
685


686
+function ($) { "use strict";
687

688
689
  // DROPDOWN CLASS DEFINITION
  // =========================
690

691
692
693
  var backdrop = '.dropdown-backdrop'
  var toggle   = '[data-toggle=dropdown]'
  var Dropdown = function (element) {
694
    var $el = $(element).on('click.bs.dropdown', this.toggle)
695
  }
696

697
698
  Dropdown.prototype.toggle = function (e) {
    var $this = $(this)
699

700
    if ($this.is('.disabled, :disabled')) return
701

702
703
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
704

705
    clearMenus()
fat's avatar
fat committed
706

707
    if (!isActive) {
fat's avatar
fat committed
708
709
      if ('ontouchstart' in document.documentElement) {
        // if mobile we we use a backdrop because click events don't delegate
Jacob Thornton's avatar
Jacob Thornton committed
710
        $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
fat's avatar
fat committed
711
      }
712
713
714
715
716
717
718
719

      $parent.trigger(e = $.Event('show.bs.dropdown'))

      if (e.isDefaultPrevented()) return

      $parent
        .toggleClass('open')
        .trigger('shown.bs.dropdown')
720
721
    }

722
    $this.focus()
723

724
725
    return false
  }
726

727
728
  Dropdown.prototype.keydown = function (e) {
    if (!/(38|40|27)/.test(e.keyCode)) return
729

730
    var $this = $(this)
731

732
733
    e.preventDefault()
    e.stopPropagation()
734

735
    if ($this.is('.disabled, :disabled')) return
736

737
738
    var $parent  = getParent($this)
    var isActive = $parent.hasClass('open')
739

740
741
742
743
    if (!isActive || (isActive && e.keyCode == 27)) {
      if (e.which == 27) $parent.find(toggle).focus()
      return $this.click()
    }
744

745
    var $items = $('[role=menu] li:not(.divider):visible a', $parent)
746

747
    if (!$items.length) return
748

749
    var index = $items.index($items.filter(':focus'))
750

751
752
753
    if (e.keyCode == 38 && index > 0)                 index--                        // up
    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
    if (!~index)                                      index=0
754

755
    $items.eq(index).focus()
756
757
  }

Mark Otto's avatar
Mark Otto committed
758
  function clearMenus() {
759
    $(backdrop).remove()
760
    $(toggle).each(function (e) {
761
762
763
764
765
766
      var $parent = getParent($(this))
      if (!$parent.hasClass('open')) return
      $parent.trigger(e = $.Event('hide.bs.dropdown'))
      if (e.isDefaultPrevented()) return
      $parent.removeClass('open').trigger('hidden.bs.dropdown')
    })
767
768
769
770
771
772
773
  }

  function getParent($this) {
    var selector = $this.attr('data-target')

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

777
    var $parent = selector && $(selector)
778

779
    return $parent && $parent.length ? $parent : $this.parent()
780
781
782
  }


783
784
  // DROPDOWN PLUGIN DEFINITION
  // ==========================
785

786
787
  var old = $.fn.dropdown

788
789
790
  $.fn.dropdown = function (option) {
    return this.each(function () {
      var $this = $(this)
791
792
      var data  = $this.data('dropdown')

793
794
795
796
797
798
799
800
      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  $.fn.dropdown.Constructor = Dropdown


801
802
  // DROPDOWN NO CONFLICT
  // ====================
803
804
805
806
807
808
809

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


810
811
812
  // APPLY TO STANDARD DROPDOWN ELEMENTS
  // ===================================

813
  $(document)
814
815
816
817
    .on('click.bs.dropdown.data-api', clearMenus)
    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
818

fat's avatar
fat committed
819
}(window.jQuery);
820

821
/* ========================================================================
fat's avatar
fat committed
822
 * Bootstrap: modal.js v3.0.0
Chris Rebert's avatar
Chris Rebert committed
823
 * http://twbs.github.com/bootstrap/javascript.html#modals
824
 * ========================================================================
825
826
827
828
829
830
831
832
833
834
835
836
837
 * 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.
838
 * ======================================================================== */
839
840


841
+function ($) { "use strict";
842

fat's avatar
fat committed
843
844
  // MODAL CLASS DEFINITION
  // ======================
845

Jacob Thornton's avatar
Jacob Thornton committed
846
  var Modal = function (element, options) {
fat's avatar
fat committed
847
    this.options   = options
fat's avatar
fat committed
848
    this.$element  = $(element).on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
fat's avatar
fat committed
849
850
    this.$backdrop =
    this.isShown   = null
851

fat's avatar
fat committed
852
853
    if (this.options.remote) this.$element.find('.modal-body').load(this.options.remote)
  }
854

fat's avatar
fat committed
855
856
857
858
859
  Modal.DEFAULTS = {
      backdrop: true
    , keyboard: true
    , show: true
  }
860

fat's avatar
fat committed
861
862
863
  Modal.prototype.toggle = function () {
    return this[!this.isShown ? 'show' : 'hide']()
  }
864

fat's avatar
fat committed
865
866
  Modal.prototype.show = function () {
    var that = this
Mark Otto's avatar
Mark Otto committed
867
    var e    = $.Event('show.bs.modal')
868

fat's avatar
fat committed
869
    this.$element.trigger(e)
870

fat's avatar
fat committed
871
    if (this.isShown || e.isDefaultPrevented()) return
872

fat's avatar
fat committed
873
    this.isShown = true
874

fat's avatar
fat committed
875
    this.escape()
876

fat's avatar
fat committed
877
878
    this.backdrop(function () {
      var transition = $.support.transition && that.$element.hasClass('fade')
879

fat's avatar
fat committed
880
      if (!that.$element.parent().length) {
Jacob Thornton's avatar
Jacob Thornton committed
881
        that.$element.appendTo(document.body) // don't move modals dom position
fat's avatar
fat committed
882
      }
883

fat's avatar
fat committed
884
      that.$element.show()
885

fat's avatar
fat committed
886
887
888
      if (transition) {
        that.$element[0].offsetWidth // force reflow
      }
889

fat's avatar
fat committed
890
891
892
      that.$element
        .addClass('in')
        .attr('aria-hidden', false)
893

fat's avatar
fat committed
894
      that.enforceFocus()
895

fat's avatar
fat committed
896
      transition ?
897
898
899
900
901
        that.$element
          .one($.support.transition.end, function () {
            that.$element.focus().trigger('shown.bs.modal')
          })
          .emulateTransitionEnd(300) :
Mark Otto's avatar
Mark Otto committed
902
        that.$element.focus().trigger('shown.bs.modal')
fat's avatar
fat committed
903
904
    })
  }
905

fat's avatar
fat committed
906
  Modal.prototype.hide = function (e) {
fat's avatar
fat committed
907
    if (e) e.preventDefault()
908

Mark Otto's avatar
Mark Otto committed
909
    e = $.Event('hide.bs.modal')
910

fat's avatar
fat committed
911
    this.$element.trigger(e)
912

fat's avatar
fat committed
913
    if (!this.isShown || e.isDefaultPrevented()) return
914

fat's avatar
fat committed
915
    this.isShown = false
916

fat's avatar
fat committed
917
    this.escape()
918

Mark Otto's avatar
Mark Otto committed
919
    $(document).off('focusin.bs.modal')
920

fat's avatar
fat committed
921
922
923
    this.$element
      .removeClass('in')
      .attr('aria-hidden', true)
924

fat's avatar
fat committed
925
    $.support.transition && this.$element.hasClass('fade') ?
926
927
928
      this.$element
        .one($.support.transition.end, $.proxy(this.hideModal, this))
        .emulateTransitionEnd(300) :
fat's avatar
fat committed
929
930
      this.hideModal()
  }
931

fat's avatar
fat committed
932
  Modal.prototype.enforceFocus = function () {
Jacob Thornton's avatar
Jacob Thornton committed
933
934
    $(document)
      .off('focusin.bs.modal') // guard against infinite focus loop
fat's avatar
fat committed
935
936
937
938
939
      .on('focusin.bs.modal', $.proxy(function (e) {
        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
          this.$element.focus()
        }
      }, this))
fat's avatar
fat committed
940
  }
941

fat's avatar
fat committed
942
943
  Modal.prototype.escape = function () {
    if (this.isShown && this.options.keyboard) {
fat's avatar
fat committed
944
      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
fat's avatar
fat committed
945
        e.which == 27 && this.hide()
fat's avatar
fat committed
946
      }, this))
fat's avatar
fat committed
947
    } else if (!this.isShown) {
Mark Otto's avatar
Mark Otto committed
948
      this.$element.off('keyup.dismiss.bs.modal')
fat's avatar
fat committed
949
950
    }
  }
951

fat's avatar
fat committed
952
953
954
955
956
  Modal.prototype.hideModal = function () {
    var that = this
    this.$element.hide()
    this.backdrop(function () {
      that.removeBackdrop()
Mark Otto's avatar
Mark Otto committed
957
      that.$element.trigger('hidden.bs.modal')
fat's avatar
fat committed
958
959
    })
  }
960

fat's avatar
fat committed
961
962
963
964
  Modal.prototype.removeBackdrop = function () {
    this.$backdrop && this.$backdrop.remove()
    this.$backdrop = null
  }
965

fat's avatar
fat committed
966
967
968
  Modal.prototype.backdrop = function (callback) {
    var that    = this
    var animate = this.$element.hasClass('fade') ? 'fade' : ''
969

fat's avatar
fat committed
970
971
    if (this.isShown && this.options.backdrop) {
      var doAnimate = $.support.transition && animate
972

fat's avatar
fat committed
973
974
      this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
        .appendTo(document.body)
975

fat's avatar
fat committed
976
977
978
979
980
981
      this.$element.on('click', $.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))
982

fat's avatar
fat committed
983
      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
984

fat's avatar
fat committed
985
      this.$backdrop.addClass('in')
986

fat's avatar
fat committed
987
      if (!callback) return
988

fat's avatar
fat committed
989
      doAnimate ?
990
991
992
        this.$backdrop
          .one($.support.transition.end, callback)
          .emulateTransitionEnd(150) :
fat's avatar
fat committed
993
        callback()
994

fat's avatar
fat committed
995
996
    } else if (!this.isShown && this.$backdrop) {
      this.$backdrop.removeClass('in')
997

fat's avatar
fat committed
998
      $.support.transition && this.$element.hasClass('fade')?
999
1000
1001
        this.$backdrop
          .one($.support.transition.end, callback)
          .emulateTransitionEnd(150) :
fat's avatar
fat committed
1002
        callback()
1003

fat's avatar
fat committed
1004
1005
1006
    } else if (callback) {
      callback()
    }
1007
1008
1009
  }


fat's avatar
fat committed
1010
1011
  // MODAL PLUGIN DEFINITION
  // =======================
1012

1013
1014
  var old = $.fn.modal

1015
1016
  $.fn.modal = function (option) {
    return this.each(function () {
fat's avatar
fat committed
1017
      var $this   = $(this)
Mark Otto's avatar
Mark Otto committed
1018
      var data    = $this.data('bs.modal')
fat's avatar
fat committed
1019
1020
      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)

Mark Otto's avatar
Mark Otto committed
1021
      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1022
1023
1024
1025
1026
1027
1028
1029
      if (typeof option == 'string') data[option]()
      else if (options.show) data.show()
    })
  }

  $.fn.modal.Constructor = Modal


fat's avatar
fat committed
1030
1031
  // MODAL NO CONFLICT
  // =================
1032
1033
1034
1035
1036
1037
1038

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


fat's avatar
fat committed
1039
1040
  // MODAL DATA-API
  // ==============
1041

Mark Otto's avatar
Mark Otto committed
1042
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
fat's avatar
fat committed
1043
1044
1045
1046
    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('modal') ? 'toggle' : $.extend({ remote:!/#/.test(href) && href }, $target.data(), $this.data())
1047

1048
    e.preventDefault()
1049

1050
1051
1052
    $target
      .modal(option)
      .one('hide', function () {
1053
        $this.is(':visible') && $this.focus()
1054
      })
Jacob Thornton's avatar
Jacob Thornton committed
1055
  })
1056

Jacob Thornton's avatar
Jacob Thornton committed
1057
1058
1059
1060
1061
  $(function () {
    var $body = $(document.body)
      .on('shown.bs.modal',  '.modal', function () { $body.addClass('modal-open') })
      .on('hidden.bs.modal', '.modal', function () { $body.removeClass('modal-open') })
  })
1062

1063
}(window.jQuery);
1064

1065
/* ========================================================================
1066
1067
1068
 * Bootstrap: tooltip.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#affix
 * Inspired by the original jQuery.tipsy by Jason Frame
1069
 * ========================================================================
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
 * 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.
1083
 * ======================================================================== */
1084
1085


1086
+function ($) { "use strict";
1087

1088
  // TOOLTIP PUBLIC CLASS DEFINITION
fat's avatar
fat committed
1089
  // ===============================
1090

1091
1092
1093
1094
1095
1096
1097
  var Tooltip = function (element, options) {
    this.type       =
    this.options    =
    this.enabled    =
    this.timeout    =
    this.hoverState =
    this.$element   = null
1098

1099
1100
    this.init('tooltip', element, options)
  }
1101

1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
  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
  }
1113

1114
1115
1116
1117
1118
  Tooltip.prototype.init = function (type, element, options) {
    this.enabled  = true
    this.type     = type
    this.$element = $(element)
    this.options  = this.getOptions(options)
1119

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

1122
1123
    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]
fat's avatar
fat committed
1124

1125
1126
1127
1128
1129
      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'
1130

1131
1132
1133
1134
        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))
      }
    }
1135

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

1141
1142
  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
1143
  }
1144

1145
1146
  Tooltip.prototype.getOptions = function (options) {
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1147

1148
1149
1150
1151
1152
1153
    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay
      , hide: options.delay
      }
    }
1154

1155
    return options
1156
  }
Jacob Thornton's avatar
Jacob Thornton committed
1157

1158
1159
1160
  Tooltip.prototype.enter = function (obj) {
    var defaults = this.getDefaults()
    var options  = {}
1161

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

1166
1167
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](options).data('bs.' + this.type)
1168

1169
    clearTimeout(self.timeout)
1170

1171
    if (!self.options.delay || !self.options.delay.show) return self.show()
1172

1173
1174
1175
1176
    self.hoverState = 'in'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
1177
  }
1178

1179
1180
1181
  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget)[this.type](this._options).data('bs.' + this.type)
1182

1183
    clearTimeout(self.timeout)
fat's avatar
fat committed
1184

1185
    if (!self.options.delay || !self.options.delay.hide) return self.hide()
1186

1187
1188
1189
1190
    self.hoverState = 'out'
    self.timeout    = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
1191
  }
1192

1193
1194
  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.'+ this.type)
1195

1196
1197
    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)
1198

1199
      if (e.isDefaultPrevented()) return
1200

1201
      var $tip = this.tip()
fat's avatar
fat committed
1202

1203
      this.setContent()
fat's avatar
fat committed
1204

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

1207
1208
1209
      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement
1210

1211
1212
1213
      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1214

1215
1216
1217
1218
      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
1219

1220
      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1221

1222
1223
1224
      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight
fat's avatar
fat committed
1225

1226
1227
      if (autoPlace) {
        var $parent = this.$element.parent()
1228

1229
1230
1231
1232
1233
        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
1234

1235
1236
1237
1238
1239
        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
1240

1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var tp = 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   }

      this.applyPlacement(tp, placement)
      this.$element.trigger('shown.bs.' + this.type)
fat's avatar
fat committed
1253
    }
1254
  }
fat's avatar
fat committed
1255

1256
1257
1258
1259
1260
  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
1261

1262
1263
1264
    // manually read margins because getBoundingClientRect includes difference
    offset.top  = offset.top  + parseInt($tip.css('margin-top'), 10)
    offset.left = offset.left + parseInt($tip.css('margin-left'), 10)
fat's avatar
fat committed
1265

1266
1267
1268
    $tip
      .offset(offset)
      .addClass('in')
fat's avatar
fat committed
1269

1270
1271
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight
fat's avatar
fat committed
1272

1273
1274
1275
    if (placement == 'top' && actualHeight != height) {
      replace = true
      offset.top  = offset.top + height - actualHeight
fat's avatar
fat committed
1276
1277
    }

1278
1279
    if (placement == 'bottom' || placement == 'top') {
      var delta = 0
1280

1281
1282
1283
      if (offset.left < 0){
        delta       = offset.left * -2
        offset.left = 0
fat's avatar
fat committed
1284

1285
        $tip.offset(offset)
1286

1287
1288
1289
        actualWidth  = $tip[0].offsetWidth
        actualHeight = $tip[0].offsetHeight
      }
1290

1291
1292
1293
1294
      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
    } else {
      this.replaceArrow(actualHeight - height, actualHeight, 'top')
    }
1295

1296
    if (replace) $tip.offset(offset)
1297
  }
1298

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

1303
1304
1305
  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()
1306

1307
1308
1309
    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
    $tip.removeClass('fade in top bottom left right')
  }
1310

1311
1312
1313
1314
  Tooltip.prototype.hide = function () {
    var that = this
    var $tip = this.tip()
    var e    = $.Event('hide.bs.' + this.type)
1315

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

1318
    this.$element.trigger(e)
1319

1320
    if (e.isDefaultPrevented()) return
1321

1322
    $tip.removeClass('in')
1323

1324
1325
    $.support.transition && this.$tip.hasClass('fade') ?
      $tip
Jacob Thornton's avatar
Jacob Thornton committed
1326
        .one($.support.transition.end, complete)
1327
        .emulateTransitionEnd(150) :
Jacob Thornton's avatar
Jacob Thornton committed
1328
      complete()
1329

1330
    this.$element.trigger('hidden.bs.' + this.type)
1331

1332
    return this
1333
1334
  }

1335
1336
1337
1338
  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', '')
1339
    }
1340
  }
1341

1342
1343
1344
  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }
1345

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

1354
1355
1356
1357
  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options
1358

1359
1360
    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
1361

1362
    return title
1363
  }
1364

1365
1366
1367
  Tooltip.prototype.tip = function () {
    return this.$tip = this.$tip || $(this.options.template)
  }
1368

1369
1370
1371
  Tooltip.prototype.arrow =function(){
    return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
  }
1372

1373
1374
1375
1376
1377
1378
1379
  Tooltip.prototype.validate = function () {
    if (!this.$element[0].parentNode) {
      this.hide()
      this.$element = null
      this.options  = null
    }
  }
1380

1381
1382
1383
  Tooltip.prototype.enable = function () {
    this.enabled = true
  }
1384

1385
1386
1387
  Tooltip.prototype.disable = function () {
    this.enabled = false
  }
1388

1389
1390
1391
  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }
Mark Otto's avatar
Mark Otto committed
1392

1393
1394
1395
1396
  Tooltip.prototype.toggle = function (e) {
    var self = e ? $(e.currentTarget)[this.type](this._options).data('bs.' + this.type) : this
    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  }
1397

1398
1399
  Tooltip.prototype.destroy = function () {
    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
fat's avatar
fat committed
1400
  }
1401
1402


1403
1404
  // TOOLTIP PLUGIN DEFINITION
  // =========================
1405

1406
  var old = $.fn.tooltip
1407

1408
  $.fn.tooltip = function (option) {
1409
    return this.each(function () {
1410
1411
1412
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option
fat's avatar
fat committed
1413

1414
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1415
1416
1417
1418
      if (typeof option == 'string') data[option]()
    })
  }

1419
  $.fn.tooltip.Constructor = Tooltip
1420

1421

1422
1423
  // TOOLTIP NO CONFLICT
  // ===================
1424

1425
1426
  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
1427
1428
1429
    return this
  }

Mark Otto's avatar
Mark Otto committed
1430
}(window.jQuery);
1431

1432
/* ========================================================================
1433
1434
 * Bootstrap: popover.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#popovers
1435
 * ========================================================================
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
 * 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.
1449
 * ======================================================================== */
1450
1451


1452
+function ($) { "use strict";
1453

1454
  // POPOVER PUBLIC CLASS DEFINITION
1455
  // ===============================
fat's avatar
fat committed
1456

1457
1458
  var Popover = function (element, options) {
    this.init('popover', element, options)
1459
1460
  }

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

1463
1464
1465
1466
1467
1468
  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>'
  })
1469

fat's avatar
fat committed
1470

1471
1472
  // NOTE: POPOVER EXTENDS tooltip.js
  // ================================
fat's avatar
fat committed
1473

1474
  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1475

1476
  Popover.prototype.constructor = Popover
fat's avatar
fat committed
1477

1478
1479
1480
  Popover.prototype.getDefaults = function () {
    return Popover.DEFAULTS
  }
1481

1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
  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')

    $tip.find('.popover-title:empty').hide()
1493
1494
  }

1495
1496
  Popover.prototype.hasContent = function () {
    return this.getTitle() || this.getContent()
1497
1498
  }

1499
1500
1501
  Popover.prototype.getContent = function () {
    var $e = this.$element
    var o  = this.options
1502

1503
1504
1505
1506
1507
    return $e.attr('data-content')
      || (typeof o.content == 'function' ?
            o.content.call($e[0]) :
            o.content)
  }
1508

1509
1510
1511
  Popover.prototype.tip = function () {
    if (!this.$tip) this.$tip = $(this.options.template)
    return this.$tip
fat's avatar
fat committed
1512
  }
1513

1514

1515
1516
  // POPOVER PLUGIN DEFINITION
  // =========================
1517

1518
  var old = $.fn.popover
1519

1520
1521
1522
1523
1524
  $.fn.popover = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.popover')
      var options = typeof option == 'object' && option
1525

1526
1527
1528
      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
      if (typeof option == 'string') data[option]()
    })
1529
1530
  }

1531
  $.fn.popover.Constructor = Popover
fat's avatar
fat committed
1532

1533

1534
1535
  // POPOVER NO CONFLICT
  // ===================
1536

1537
1538
1539
1540
  $.fn.popover.noConflict = function () {
    $.fn.popover = old
    return this
  }
1541

1542
}(window.jQuery);
1543

1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
/* ========================================================================
 * 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.
 * ======================================================================== */
1562
1563


1564
+function ($) { "use strict";
1565

1566
1567
  // SCROLLSPY CLASS DEFINITION
  // ==========================
1568

1569
1570
1571
  function ScrollSpy(element, options) {
    var href
    var process  = $.proxy(this.process, this)
1572

fat's avatar
fat committed
1573
    this.$element       = $(element).is('body') ? $(window) : $(element)
1574
    this.$body          = $('body')
fat's avatar
fat committed
1575
    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)
1576
1577
1578
1579
1580
1581
1582
    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
1583

1584
1585
1586
    this.refresh()
    this.process()
  }
1587

1588
1589
1590
  ScrollSpy.DEFAULTS = {
    offset: 10
  }
1591

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

1595
1596
    this.offsets = $([])
    this.targets = $([])
1597

1598
1599
1600
1601
1602
1603
1604
    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)
1605

1606
1607
        return ($href
          && $href.length
fat's avatar
fat committed
1608
          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
1609
1610
1611
1612
1613
1614
1615
      })
      .sort(function (a, b) { return a[0] - b[0] })
      .each(function () {
        self.offsets.push(this[0])
        self.targets.push(this[1])
      })
  }
1616

1617
1618
1619
1620
1621
1622
1623
1624
  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
1625

1626
1627
1628
    if (scrollTop >= maxScroll) {
      return activeTarget != (i = targets.last()[0]) && this.activate(i)
    }
1629

1630
1631
1632
1633
1634
    for (i = offsets.length; i--;) {
      activeTarget != targets[i]
        && scrollTop >= offsets[i]
        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
        && this.activate( targets[i] )
1635
    }
1636
1637
  }

1638
1639
  ScrollSpy.prototype.activate = function (target) {
    this.activeTarget = target
1640

1641
1642
1643
    $(this.selector)
      .parents('.active')
      .removeClass('active')
1644

1645
1646
1647
    var selector = this.selector
      + '[data-target="' + target + '"],'
      + this.selector + '[href="' + target + '"]'
1648

1649
1650
1651
    var active = $(selector)
      .parents('li')
      .addClass('active')
1652

1653
1654
1655
1656
    if (active.parent('.dropdown-menu').length)  {
      active = active
        .closest('li.dropdown')
        .addClass('active')
1657
    }
1658

1659
1660
    active.trigger('activate')
  }
1661
1662


1663
1664
  // SCROLLSPY PLUGIN DEFINITION
  // ===========================
1665

1666
  var old = $.fn.scrollspy
1667

1668
1669
1670
1671
1672
  $.fn.scrollspy = function (option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.scrollspy')
      var options = typeof option == 'object' && option
1673

1674
1675
1676
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
      if (typeof option == 'string') data[option]()
    })
1677
1678
  }

1679
  $.fn.scrollspy.Constructor = ScrollSpy
1680
1681


1682
1683
1684
1685
1686
1687
  // SCROLLSPY NO CONFLICT
  // =====================

  $.fn.scrollspy.noConflict = function () {
    $.fn.scrollspy = old
    return this
1688
1689
1690
  }


1691
1692
  // SCROLLSPY DATA-API
  // ==================
1693

1694
1695
1696
1697
1698
1699
  $(window).on('load', function () {
    $('[data-spy="scroll"]').each(function () {
      var $spy = $(this)
      $spy.scrollspy($spy.data())
    })
  })
1700

1701
}(window.jQuery);
1702

1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
/* ========================================================================
 * 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.
 * ======================================================================== */
1721

1722

1723
1724
1725
1726
1727
1728
1729
+function ($) { "use strict";

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

  var Tab = function (element) {
    this.element = $(element)
1730
  }
1731

1732
1733
1734
1735
1736
1737
1738
1739
  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
1740
    }
1741

1742
    if ($this.parent('li').hasClass('active')) return
1743

1744
1745
1746
1747
    var previous = $ul.find('.active:last a')[0]
    var e        = $.Event('show.bs.tab', {
      relatedTarget: previous
    })
1748

1749
    $this.trigger(e)
1750

1751
    if (e.isDefaultPrevented()) return
1752

1753
    var $target = $(selector)
1754

1755
1756
1757
1758
1759
1760
1761
    this.activate($this.parent('li'), $ul)
    this.activate($target, $target.parent(), function () {
      $this.trigger({
        type: 'shown.bs.tab'
      , relatedTarget: previous
      })
    })
1762
  }
1763

1764
1765
1766
1767
1768
  Tab.prototype.activate = function (element, container, callback) {
    var $active    = container.find('> .active')
    var transition = callback
      && $.support.transition
      && $active.hasClass('fade')
1769

1770
1771
1772
1773
1774
    function next() {
      $active
        .removeClass('active')
        .find('> .dropdown-menu > .active')
        .removeClass('active')
1775

1776
      element.addClass('active')
1777

1778
1779
1780
1781
1782
1783
      if (transition) {
        element[0].offsetWidth // reflow for transition
        element.addClass('in')
      } else {
        element.removeClass('fade')
      }
1784

1785
1786
1787
      if (element.parent('.dropdown-menu')) {
        element.closest('li.dropdown').addClass('active')
      }
fat's avatar
fat committed
1788

1789
1790
      callback && callback()
    }
fat's avatar
fat committed
1791

1792
1793
1794
1795
1796
1797
1798
    transition ?
      $active
        .one($.support.transition.end, next)
        .emulateTransitionEnd(150) :
      next()

    $active.removeClass('in')
1799
1800
1801
  }


1802
1803
  // TAB PLUGIN DEFINITION
  // =====================
1804

1805
  var old = $.fn.tab
1806

1807
  $.fn.tab = function ( option ) {
1808
    return this.each(function () {
1809
1810
      var $this = $(this)
      var data  = $this.data('bs.tab')
fat's avatar
fat committed
1811

1812
      if (!data) $this.data('bs.tab', (data = new Tab(this)))
1813
1814
1815
1816
      if (typeof option == 'string') data[option]()
    })
  }

1817
  $.fn.tab.Constructor = Tab
1818
1819


1820
1821
  // TAB NO CONFLICT
  // ===============
1822

1823
1824
  $.fn.tab.noConflict = function () {
    $.fn.tab = old
1825
1826
1827
    return this
  }

1828
1829
1830
1831
1832
1833
1834
1835
1836

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

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

1837
}(window.jQuery);
1838

1839
/* ========================================================================
1840
1841
 * Bootstrap: affix.js v3.0.0
 * http://twbs.github.com/bootstrap/javascript.html#affix
1842
 * ========================================================================
1843
 * Copyright 2012 Twitter, Inc.
Mark Otto's avatar
Mark Otto committed
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
 *
 * 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.
1856
 * ======================================================================== */
Mark Otto's avatar
Mark Otto committed
1857
1858


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

1861
1862
  // AFFIX CLASS DEFINITION
  // ======================
Mark Otto's avatar
Mark Otto committed
1863

1864
1865
1866
1867
1868
  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
1869

1870
1871
1872
    this.$element = $(element)
    this.affixed  =
    this.unpin    = null
fat's avatar
fat committed
1873

1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
    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() })
1915
    }
Mark Otto's avatar
Mark Otto committed
1916
1917
  }

1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932

  // 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]()
    })
1933
1934
  }

1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
  $.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
1962
1963
  })

1964
}(window.jQuery);