GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

third-party/bootstrap/bootstrap-3.3.7-dist/js/bootstrap.js   F
last analyzed

Complexity

Total Complexity 449
Complexity/F 2.36

Size

Lines of Code 2371
Function Count 190

Duplication

Duplicated Lines 22
Ratio 0.93 %

Importance

Changes 0
Metric Value
eloc 1345
dl 22
loc 2371
rs 0.8
c 0
b 0
f 0
wmc 449
mnd 259
bc 259
fnc 190
bpm 1.3631
cpm 2.3631
noi 6

9 Functions

Rating   Name   Duplication   Size   Complexity  
A bootstrap.js ➔ ScrollSpy 0 14 4
C bootstrap.js ➔ getParent 0 12 9
F bootstrap.js ➔ Plugin 0 9 33
B bootstrap.js ➔ clearMenus 0 20 6
F bootstrap.js ➔ next 0 32 14
F bootstrap.js ➔ removeElement 0 4 17
B bootstrap.js ➔ transitionEnd 0 18 7
F bootstrap.js ➔ getTargetFromTrigger 0 7 32
F bootstrap.js ➔ complete 0 9 77

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like third-party/bootstrap/bootstrap-3.3.7-dist/js/bootstrap.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*!
2
 * Bootstrap v3.3.7 (http://getbootstrap.com)
3
 * Copyright 2011-2016 Twitter, Inc.
4
 * Licensed under the MIT license
5
 */
6
7
if (typeof jQuery === 'undefined') {
8
  throw new Error('Bootstrap\'s JavaScript requires jQuery')
9
}
10
11
+function ($) {
12
  'use strict';
13
  var version = $.fn.jquery.split(' ')[0].split('.')
14
  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) {
15
    throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4')
16
  }
17
}(jQuery);
18
19
/* ========================================================================
20
 * Bootstrap: transition.js v3.3.7
21
 * http://getbootstrap.com/javascript/#transitions
22
 * ========================================================================
23
 * Copyright 2011-2016 Twitter, Inc.
24
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
25
 * ======================================================================== */
26
27
28
+function ($) {
29
  'use strict';
30
31
  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
32
  // ============================================================
33
34
  function transitionEnd() {
35
    var el = document.createElement('bootstrap')
36
37
    var transEndEventNames = {
38
      WebkitTransition : 'webkitTransitionEnd',
39
      MozTransition    : 'transitionend',
40
      OTransition      : 'oTransitionEnd otransitionend',
41
      transition       : 'transitionend'
42
    }
43
44
    for (var name in transEndEventNames) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
45
      if (el.style[name] !== undefined) {
46
        return { end: transEndEventNames[name] }
47
      }
48
    }
49
50
    return false // explicit for ie8 (  ._.)
51
  }
52
53
  // http://blog.alexmaccaw.com/css-transitions
54
  $.fn.emulateTransitionEnd = function (duration) {
55
    var called = false
56
    var $el = this
57
    $(this).one('bsTransitionEnd', function () { called = true })
58
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
59
    setTimeout(callback, duration)
60
    return this
61
  }
62
63
  $(function () {
64
    $.support.transition = transitionEnd()
65
66
    if (!$.support.transition) return
67
68
    $.event.special.bsTransitionEnd = {
69
      bindType: $.support.transition.end,
70
      delegateType: $.support.transition.end,
71
      handle: function (e) {
72
        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
73
      }
74
    }
75
  })
76
77
}(jQuery);
78
79
/* ========================================================================
80
 * Bootstrap: alert.js v3.3.7
81
 * http://getbootstrap.com/javascript/#alerts
82
 * ========================================================================
83
 * Copyright 2011-2016 Twitter, Inc.
84
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
85
 * ======================================================================== */
86
87
88
+function ($) {
89
  'use strict';
90
91
  // ALERT CLASS DEFINITION
92
  // ======================
93
94
  var dismiss = '[data-dismiss="alert"]'
95
  var Alert   = function (el) {
96
    $(el).on('click', dismiss, this.close)
97
  }
98
99
  Alert.VERSION = '3.3.7'
100
101
  Alert.TRANSITION_DURATION = 150
102
103
  Alert.prototype.close = function (e) {
104
    var $this    = $(this)
105
    var selector = $this.attr('data-target')
106
107
    if (!selector) {
108
      selector = $this.attr('href')
109
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
110
    }
111
112
    var $parent = $(selector === '#' ? [] : selector)
113
114
    if (e) e.preventDefault()
115
116
    if (!$parent.length) {
117
      $parent = $this.closest('.alert')
118
    }
119
120
    $parent.trigger(e = $.Event('close.bs.alert'))
121
122
    if (e.isDefaultPrevented()) return
123
124
    $parent.removeClass('in')
125
126
    function removeElement() {
127
      // detach from parent, fire event then clean up data
128
      $parent.detach().trigger('closed.bs.alert').remove()
129
    }
130
131
    $.support.transition && $parent.hasClass('fade') ?
132
      $parent
133
        .one('bsTransitionEnd', removeElement)
134
        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
135
      removeElement()
136
  }
137
138
139
  // ALERT PLUGIN DEFINITION
140
  // =======================
141
142
  function Plugin(option) {
143
    return this.each(function () {
144
      var $this = $(this)
145
      var data  = $this.data('bs.alert')
146
147
      if (!data) $this.data('bs.alert', (data = new Alert(this)))
148
      if (typeof option == 'string') data[option].call($this)
149
    })
150
  }
151
152
  var old = $.fn.alert
153
154
  $.fn.alert             = Plugin
155
  $.fn.alert.Constructor = Alert
156
157
158
  // ALERT NO CONFLICT
159
  // =================
160
161
  $.fn.alert.noConflict = function () {
162
    $.fn.alert = old
163
    return this
164
  }
165
166
167
  // ALERT DATA-API
168
  // ==============
169
170
  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
171
172
}(jQuery);
173
174
/* ========================================================================
175
 * Bootstrap: button.js v3.3.7
176
 * http://getbootstrap.com/javascript/#buttons
177
 * ========================================================================
178
 * Copyright 2011-2016 Twitter, Inc.
179
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
180
 * ======================================================================== */
181
182
183
+function ($) {
184
  'use strict';
185
186
  // BUTTON PUBLIC CLASS DEFINITION
187
  // ==============================
188
189
  var Button = function (element, options) {
190
    this.$element  = $(element)
191
    this.options   = $.extend({}, Button.DEFAULTS, options)
192
    this.isLoading = false
193
  }
194
195
  Button.VERSION  = '3.3.7'
196
197
  Button.DEFAULTS = {
198
    loadingText: 'loading...'
199
  }
200
201
  Button.prototype.setState = function (state) {
202
    var d    = 'disabled'
203
    var $el  = this.$element
204
    var val  = $el.is('input') ? 'val' : 'html'
205
    var data = $el.data()
206
207
    state += 'Text'
208
209
    if (data.resetText == null) $el.data('resetText', $el[val]())
210
211
    // push to event loop to allow forms to submit
212
    setTimeout($.proxy(function () {
213
      $el[val](data[state] == null ? this.options[state] : data[state])
214
215
      if (state == 'loadingText') {
216
        this.isLoading = true
217
        $el.addClass(d).attr(d, d).prop(d, true)
218
      } else if (this.isLoading) {
219
        this.isLoading = false
220
        $el.removeClass(d).removeAttr(d).prop(d, false)
221
      }
222
    }, this), 0)
223
  }
224
225
  Button.prototype.toggle = function () {
226
    var changed = true
227
    var $parent = this.$element.closest('[data-toggle="buttons"]')
228
229
    if ($parent.length) {
230
      var $input = this.$element.find('input')
231
      if ($input.prop('type') == 'radio') {
232
        if ($input.prop('checked')) changed = false
233
        $parent.find('.active').removeClass('active')
234
        this.$element.addClass('active')
235
      } else if ($input.prop('type') == 'checkbox') {
236
        if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
237
        this.$element.toggleClass('active')
238
      }
239
      $input.prop('checked', this.$element.hasClass('active'))
240
      if (changed) $input.trigger('change')
241
    } else {
242
      this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
243
      this.$element.toggleClass('active')
244
    }
245
  }
246
247
248
  // BUTTON PLUGIN DEFINITION
249
  // ========================
250
251
  function Plugin(option) {
252
    return this.each(function () {
253
      var $this   = $(this)
254
      var data    = $this.data('bs.button')
255
      var options = typeof option == 'object' && option
256
257
      if (!data) $this.data('bs.button', (data = new Button(this, options)))
258
259
      if (option == 'toggle') data.toggle()
260
      else if (option) data.setState(option)
261
    })
262
  }
263
264
  var old = $.fn.button
265
266
  $.fn.button             = Plugin
267
  $.fn.button.Constructor = Button
268
269
270
  // BUTTON NO CONFLICT
271
  // ==================
272
273
  $.fn.button.noConflict = function () {
274
    $.fn.button = old
275
    return this
276
  }
277
278
279
  // BUTTON DATA-API
280
  // ===============
281
282
  $(document)
283
    .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
284
      var $btn = $(e.target).closest('.btn')
285
      Plugin.call($btn, 'toggle')
286
      if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
287
        // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
288
        e.preventDefault()
289
        // The target component still receive the focus
290
        if ($btn.is('input,button')) $btn.trigger('focus')
291
        else $btn.find('input:visible,button:visible').first().trigger('focus')
292
      }
293
    })
294
    .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
295
      $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
296
    })
297
298
}(jQuery);
299
300
/* ========================================================================
301
 * Bootstrap: carousel.js v3.3.7
302
 * http://getbootstrap.com/javascript/#carousel
303
 * ========================================================================
304
 * Copyright 2011-2016 Twitter, Inc.
305
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
306
 * ======================================================================== */
307
308
309
+function ($) {
310
  'use strict';
311
312
  // CAROUSEL CLASS DEFINITION
313
  // =========================
314
315
  var Carousel = function (element, options) {
316
    this.$element    = $(element)
317
    this.$indicators = this.$element.find('.carousel-indicators')
318
    this.options     = options
319
    this.paused      = null
320
    this.sliding     = null
321
    this.interval    = null
322
    this.$active     = null
323
    this.$items      = null
324
325
    this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
326
327
    this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element
328
      .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
329
      .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
330
  }
331
332
  Carousel.VERSION  = '3.3.7'
333
334
  Carousel.TRANSITION_DURATION = 600
335
336
  Carousel.DEFAULTS = {
337
    interval: 5000,
338
    pause: 'hover',
339
    wrap: true,
340
    keyboard: true
341
  }
342
343
  Carousel.prototype.keydown = function (e) {
344
    if (/input|textarea/i.test(e.target.tagName)) return
345
    switch (e.which) {
346
      case 37: this.prev(); break
347
      case 39: this.next(); break
348
      default: return
349
    }
350
351
    e.preventDefault()
352
  }
353
354
  Carousel.prototype.cycle = function (e) {
355
    e || (this.paused = false)
356
357
    this.interval && clearInterval(this.interval)
358
359
    this.options.interval
360
      && !this.paused
361
      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
362
363
    return this
364
  }
365
366
  Carousel.prototype.getItemIndex = function (item) {
367
    this.$items = item.parent().children('.item')
368
    return this.$items.index(item || this.$active)
369
  }
370
371
  Carousel.prototype.getItemForDirection = function (direction, active) {
372
    var activeIndex = this.getItemIndex(active)
373
    var willWrap = (direction == 'prev' && activeIndex === 0)
374
                || (direction == 'next' && activeIndex == (this.$items.length - 1))
375
    if (willWrap && !this.options.wrap) return active
376
    var delta = direction == 'prev' ? -1 : 1
377
    var itemIndex = (activeIndex + delta) % this.$items.length
378
    return this.$items.eq(itemIndex)
379
  }
380
381
  Carousel.prototype.to = function (pos) {
382
    var that        = this
383
    var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
384
385
    if (pos > (this.$items.length - 1) || pos < 0) return
386
387
    if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
388
    if (activeIndex == pos) return this.pause().cycle()
389
390
    return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
391
  }
392
393
  Carousel.prototype.pause = function (e) {
394
    e || (this.paused = true)
395
396
    if (this.$element.find('.next, .prev').length && $.support.transition) {
397
      this.$element.trigger($.support.transition.end)
398
      this.cycle(true)
399
    }
400
401
    this.interval = clearInterval(this.interval)
402
403
    return this
404
  }
405
406
  Carousel.prototype.next = function () {
407
    if (this.sliding) return
408
    return this.slide('next')
409
  }
410
411
  Carousel.prototype.prev = function () {
412
    if (this.sliding) return
413
    return this.slide('prev')
414
  }
415
416
  Carousel.prototype.slide = function (type, next) {
417
    var $active   = this.$element.find('.item.active')
418
    var $next     = next || this.getItemForDirection(type, $active)
419
    var isCycling = this.interval
420
    var direction = type == 'next' ? 'left' : 'right'
421
    var that      = this
422
423
    if ($next.hasClass('active')) return (this.sliding = false)
424
425
    var relatedTarget = $next[0]
426
    var slideEvent = $.Event('slide.bs.carousel', {
427
      relatedTarget: relatedTarget,
428
      direction: direction
429
    })
430
    this.$element.trigger(slideEvent)
431
    if (slideEvent.isDefaultPrevented()) return
432
433
    this.sliding = true
434
435
    isCycling && this.pause()
436
437
    if (this.$indicators.length) {
438
      this.$indicators.find('.active').removeClass('active')
439
      var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
440
      $nextIndicator && $nextIndicator.addClass('active')
441
    }
442
443
    var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
444
    if ($.support.transition && this.$element.hasClass('slide')) {
445
      $next.addClass(type)
446
      $next[0].offsetWidth // force reflow
0 ignored issues
show
introduced by
The result of the property access to $next.0.offsetWidth is not used.
Loading history...
447
      $active.addClass(direction)
448
      $next.addClass(direction)
449
      $active
450
        .one('bsTransitionEnd', function () {
451
          $next.removeClass([type, direction].join(' ')).addClass('active')
452
          $active.removeClass(['active', direction].join(' '))
453
          that.sliding = false
454
          setTimeout(function () {
455
            that.$element.trigger(slidEvent)
456
          }, 0)
457
        })
458
        .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
459
    } else {
460
      $active.removeClass('active')
461
      $next.addClass('active')
462
      this.sliding = false
463
      this.$element.trigger(slidEvent)
464
    }
465
466
    isCycling && this.cycle()
467
468
    return this
469
  }
470
471
472
  // CAROUSEL PLUGIN DEFINITION
473
  // ==========================
474
475
  function Plugin(option) {
476
    return this.each(function () {
477
      var $this   = $(this)
478
      var data    = $this.data('bs.carousel')
479
      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
480
      var action  = typeof option == 'string' ? option : options.slide
481
482
      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
483
      if (typeof option == 'number') data.to(option)
484
      else if (action) data[action]()
485
      else if (options.interval) data.pause().cycle()
486
    })
487
  }
488
489
  var old = $.fn.carousel
490
491
  $.fn.carousel             = Plugin
492
  $.fn.carousel.Constructor = Carousel
493
494
495
  // CAROUSEL NO CONFLICT
496
  // ====================
497
498
  $.fn.carousel.noConflict = function () {
499
    $.fn.carousel = old
500
    return this
501
  }
502
503
504
  // CAROUSEL DATA-API
505
  // =================
506
507
  var clickHandler = function (e) {
508
    var href
509
    var $this   = $(this)
510
    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
511
    if (!$target.hasClass('carousel')) return
512
    var options = $.extend({}, $target.data(), $this.data())
513
    var slideIndex = $this.attr('data-slide-to')
514
    if (slideIndex) options.interval = false
515
516
    Plugin.call($target, options)
517
518
    if (slideIndex) {
519
      $target.data('bs.carousel').to(slideIndex)
520
    }
521
522
    e.preventDefault()
523
  }
524
525
  $(document)
526
    .on('click.bs.carousel.data-api', '[data-slide]', clickHandler)
527
    .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler)
528
529
  $(window).on('load', function () {
530
    $('[data-ride="carousel"]').each(function () {
531
      var $carousel = $(this)
532
      Plugin.call($carousel, $carousel.data())
533
    })
534
  })
535
536
}(jQuery);
537
538
/* ========================================================================
539
 * Bootstrap: collapse.js v3.3.7
540
 * http://getbootstrap.com/javascript/#collapse
541
 * ========================================================================
542
 * Copyright 2011-2016 Twitter, Inc.
543
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
544
 * ======================================================================== */
545
546
/* jshint latedef: false */
547
548
+function ($) {
549
  'use strict';
550
551
  // COLLAPSE PUBLIC CLASS DEFINITION
552
  // ================================
553
554
  var Collapse = function (element, options) {
555
    this.$element      = $(element)
556
    this.options       = $.extend({}, Collapse.DEFAULTS, options)
557
    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
558
                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
559
    this.transitioning = null
560
561
    if (this.options.parent) {
562
      this.$parent = this.getParent()
563
    } else {
564
      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
565
    }
566
567
    if (this.options.toggle) this.toggle()
568
  }
569
570
  Collapse.VERSION  = '3.3.7'
571
572
  Collapse.TRANSITION_DURATION = 350
573
574
  Collapse.DEFAULTS = {
575
    toggle: true
576
  }
577
578
  Collapse.prototype.dimension = function () {
579
    var hasWidth = this.$element.hasClass('width')
580
    return hasWidth ? 'width' : 'height'
581
  }
582
583
  Collapse.prototype.show = function () {
584
    if (this.transitioning || this.$element.hasClass('in')) return
585
586
    var activesData
587
    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')
588
589
    if (actives && actives.length) {
590
      activesData = actives.data('bs.collapse')
591
      if (activesData && activesData.transitioning) return
592
    }
593
594
    var startEvent = $.Event('show.bs.collapse')
595
    this.$element.trigger(startEvent)
596
    if (startEvent.isDefaultPrevented()) return
597
598
    if (actives && actives.length) {
599
      Plugin.call(actives, 'hide')
600
      activesData || actives.data('bs.collapse', null)
601
    }
602
603
    var dimension = this.dimension()
604
605
    this.$element
606
      .removeClass('collapse')
607
      .addClass('collapsing')[dimension](0)
608
      .attr('aria-expanded', true)
609
610
    this.$trigger
611
      .removeClass('collapsed')
612
      .attr('aria-expanded', true)
613
614
    this.transitioning = 1
615
616
    var complete = function () {
617
      this.$element
618
        .removeClass('collapsing')
619
        .addClass('collapse in')[dimension]('')
620
      this.transitioning = 0
621
      this.$element
622
        .trigger('shown.bs.collapse')
623
    }
624
625
    if (!$.support.transition) return complete.call(this)
626
627
    var scrollSize = $.camelCase(['scroll', dimension].join('-'))
628
629
    this.$element
630
      .one('bsTransitionEnd', $.proxy(complete, this))
631
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
632
  }
633
634
  Collapse.prototype.hide = function () {
635
    if (this.transitioning || !this.$element.hasClass('in')) return
636
637
    var startEvent = $.Event('hide.bs.collapse')
638
    this.$element.trigger(startEvent)
639
    if (startEvent.isDefaultPrevented()) return
640
641
    var dimension = this.dimension()
642
643
    this.$element[dimension](this.$element[dimension]())[0].offsetHeight
0 ignored issues
show
introduced by
The result of the property access to this.$element.dimension(...nsion()).0.offsetHeight is not used.
Loading history...
644
645
    this.$element
646
      .addClass('collapsing')
647
      .removeClass('collapse in')
648
      .attr('aria-expanded', false)
649
650
    this.$trigger
651
      .addClass('collapsed')
652
      .attr('aria-expanded', false)
653
654
    this.transitioning = 1
655
656
    var complete = function () {
657
      this.transitioning = 0
658
      this.$element
659
        .removeClass('collapsing')
660
        .addClass('collapse')
661
        .trigger('hidden.bs.collapse')
662
    }
663
664
    if (!$.support.transition) return complete.call(this)
665
666
    this.$element
667
      [dimension](0)
668
      .one('bsTransitionEnd', $.proxy(complete, this))
669
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
670
  }
671
672
  Collapse.prototype.toggle = function () {
673
    this[this.$element.hasClass('in') ? 'hide' : 'show']()
674
  }
675
676
  Collapse.prototype.getParent = function () {
677
    return $(this.options.parent)
678
      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
679
      .each($.proxy(function (i, element) {
680
        var $element = $(element)
681
        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
682
      }, this))
683
      .end()
684
  }
685
686
  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
687
    var isOpen = $element.hasClass('in')
688
689
    $element.attr('aria-expanded', isOpen)
690
    $trigger
691
      .toggleClass('collapsed', !isOpen)
692
      .attr('aria-expanded', isOpen)
693
  }
694
695
  function getTargetFromTrigger($trigger) {
696
    var href
697
    var target = $trigger.attr('data-target')
698
      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
699
700
    return $(target)
701
  }
702
703
704
  // COLLAPSE PLUGIN DEFINITION
705
  // ==========================
706
707
  function Plugin(option) {
708
    return this.each(function () {
709
      var $this   = $(this)
710
      var data    = $this.data('bs.collapse')
711
      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
712
713
      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
714
      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
715
      if (typeof option == 'string') data[option]()
716
    })
717
  }
718
719
  var old = $.fn.collapse
720
721
  $.fn.collapse             = Plugin
722
  $.fn.collapse.Constructor = Collapse
723
724
725
  // COLLAPSE NO CONFLICT
726
  // ====================
727
728
  $.fn.collapse.noConflict = function () {
729
    $.fn.collapse = old
730
    return this
731
  }
732
733
734
  // COLLAPSE DATA-API
735
  // =================
736
737
  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
738
    var $this   = $(this)
739
740
    if (!$this.attr('data-target')) e.preventDefault()
741
742
    var $target = getTargetFromTrigger($this)
743
    var data    = $target.data('bs.collapse')
744
    var option  = data ? 'toggle' : $this.data()
745
746
    Plugin.call($target, option)
747
  })
748
749
}(jQuery);
750
751
/* ========================================================================
752
 * Bootstrap: dropdown.js v3.3.7
753
 * http://getbootstrap.com/javascript/#dropdowns
754
 * ========================================================================
755
 * Copyright 2011-2016 Twitter, Inc.
756
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
757
 * ======================================================================== */
758
759
760
+function ($) {
761
  'use strict';
762
763
  // DROPDOWN CLASS DEFINITION
764
  // =========================
765
766
  var backdrop = '.dropdown-backdrop'
767
  var toggle   = '[data-toggle="dropdown"]'
768
  var Dropdown = function (element) {
769
    $(element).on('click.bs.dropdown', this.toggle)
770
  }
771
772
  Dropdown.VERSION = '3.3.7'
773
774
  function getParent($this) {
775
    var selector = $this.attr('data-target')
776
777
    if (!selector) {
778
      selector = $this.attr('href')
779
      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
780
    }
781
782
    var $parent = selector && $(selector)
783
784
    return $parent && $parent.length ? $parent : $this.parent()
785
  }
786
787
  function clearMenus(e) {
788
    if (e && e.which === 3) return
789
    $(backdrop).remove()
790
    $(toggle).each(function () {
791
      var $this         = $(this)
792
      var $parent       = getParent($this)
793
      var relatedTarget = { relatedTarget: this }
794
795
      if (!$parent.hasClass('open')) return
796
797
      if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
798
799
      $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
800
801
      if (e.isDefaultPrevented()) return
802
803
      $this.attr('aria-expanded', 'false')
804
      $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
805
    })
806
  }
807
808
  Dropdown.prototype.toggle = function (e) {
809
    var $this = $(this)
810
811
    if ($this.is('.disabled, :disabled')) return
812
813
    var $parent  = getParent($this)
814
    var isActive = $parent.hasClass('open')
815
816
    clearMenus()
817
818
    if (!isActive) {
819
      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
820
        // if mobile we use a backdrop because click events don't delegate
821
        $(document.createElement('div'))
822
          .addClass('dropdown-backdrop')
823
          .insertAfter($(this))
824
          .on('click', clearMenus)
825
      }
826
827
      var relatedTarget = { relatedTarget: this }
828
      $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
829
830
      if (e.isDefaultPrevented()) return
831
832
      $this
833
        .trigger('focus')
834
        .attr('aria-expanded', 'true')
835
836
      $parent
837
        .toggleClass('open')
838
        .trigger($.Event('shown.bs.dropdown', relatedTarget))
839
    }
840
841
    return false
842
  }
843
844
  Dropdown.prototype.keydown = function (e) {
845
    if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
846
847
    var $this = $(this)
848
849
    e.preventDefault()
850
    e.stopPropagation()
851
852
    if ($this.is('.disabled, :disabled')) return
853
854
    var $parent  = getParent($this)
855
    var isActive = $parent.hasClass('open')
856
857
    if (!isActive && e.which != 27 || isActive && e.which == 27) {
858
      if (e.which == 27) $parent.find(toggle).trigger('focus')
859
      return $this.trigger('click')
860
    }
861
862
    var desc = ' li:not(.disabled):visible a'
863
    var $items = $parent.find('.dropdown-menu' + desc)
864
865
    if (!$items.length) return
866
867
    var index = $items.index(e.target)
868
869
    if (e.which == 38 && index > 0)                 index--         // up
870
    if (e.which == 40 && index < $items.length - 1) index++         // down
871
    if (!~index)                                    index = 0
872
873
    $items.eq(index).trigger('focus')
874
  }
875
876
877
  // DROPDOWN PLUGIN DEFINITION
878
  // ==========================
879
880
  function Plugin(option) {
881
    return this.each(function () {
882
      var $this = $(this)
883
      var data  = $this.data('bs.dropdown')
884
885
      if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
886
      if (typeof option == 'string') data[option].call($this)
887
    })
888
  }
889
890
  var old = $.fn.dropdown
891
892
  $.fn.dropdown             = Plugin
893
  $.fn.dropdown.Constructor = Dropdown
894
895
896
  // DROPDOWN NO CONFLICT
897
  // ====================
898
899
  $.fn.dropdown.noConflict = function () {
900
    $.fn.dropdown = old
901
    return this
902
  }
903
904
905
  // APPLY TO STANDARD DROPDOWN ELEMENTS
906
  // ===================================
907
908
  $(document)
909
    .on('click.bs.dropdown.data-api', clearMenus)
910
    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
911
    .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
912
    .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
913
    .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
914
915
}(jQuery);
916
917
/* ========================================================================
918
 * Bootstrap: modal.js v3.3.7
919
 * http://getbootstrap.com/javascript/#modals
920
 * ========================================================================
921
 * Copyright 2011-2016 Twitter, Inc.
922
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
923
 * ======================================================================== */
924
925
926
+function ($) {
927
  'use strict';
928
929
  // MODAL CLASS DEFINITION
930
  // ======================
931
932
  var Modal = function (element, options) {
933
    this.options             = options
934
    this.$body               = $(document.body)
935
    this.$element            = $(element)
936
    this.$dialog             = this.$element.find('.modal-dialog')
937
    this.$backdrop           = null
938
    this.isShown             = null
939
    this.originalBodyPad     = null
940
    this.scrollbarWidth      = 0
941
    this.ignoreBackdropClick = false
942
943
    if (this.options.remote) {
944
      this.$element
945
        .find('.modal-content')
946
        .load(this.options.remote, $.proxy(function () {
947
          this.$element.trigger('loaded.bs.modal')
948
        }, this))
949
    }
950
  }
951
952
  Modal.VERSION  = '3.3.7'
953
954
  Modal.TRANSITION_DURATION = 300
955
  Modal.BACKDROP_TRANSITION_DURATION = 150
956
957
  Modal.DEFAULTS = {
958
    backdrop: true,
959
    keyboard: true,
960
    show: true
961
  }
962
963
  Modal.prototype.toggle = function (_relatedTarget) {
964
    return this.isShown ? this.hide() : this.show(_relatedTarget)
965
  }
966
967
  Modal.prototype.show = function (_relatedTarget) {
968
    var that = this
969
    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
970
971
    this.$element.trigger(e)
972
973
    if (this.isShown || e.isDefaultPrevented()) return
974
975
    this.isShown = true
976
977
    this.checkScrollbar()
978
    this.setScrollbar()
979
    this.$body.addClass('modal-open')
980
981
    this.escape()
982
    this.resize()
983
984
    this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
985
986
    this.$dialog.on('mousedown.dismiss.bs.modal', function () {
987
      that.$element.one('mouseup.dismiss.bs.modal', function (e) {
988
        if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true
989
      })
990
    })
991
992
    this.backdrop(function () {
993
      var transition = $.support.transition && that.$element.hasClass('fade')
994
995
      if (!that.$element.parent().length) {
996
        that.$element.appendTo(that.$body) // don't move modals dom position
997
      }
998
999
      that.$element
1000
        .show()
1001
        .scrollTop(0)
1002
1003
      that.adjustDialog()
1004
1005
      if (transition) {
1006
        that.$element[0].offsetWidth // force reflow
0 ignored issues
show
introduced by
The result of the property access to that.$element.0.offsetWidth is not used.
Loading history...
1007
      }
1008
1009
      that.$element.addClass('in')
1010
1011
      that.enforceFocus()
1012
1013
      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
1014
1015
      transition ?
1016
        that.$dialog // wait for modal to slide in
1017
          .one('bsTransitionEnd', function () {
1018
            that.$element.trigger('focus').trigger(e)
1019
          })
1020
          .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1021
        that.$element.trigger('focus').trigger(e)
1022
    })
1023
  }
1024
1025
  Modal.prototype.hide = function (e) {
1026
    if (e) e.preventDefault()
1027
1028
    e = $.Event('hide.bs.modal')
1029
1030
    this.$element.trigger(e)
1031
1032
    if (!this.isShown || e.isDefaultPrevented()) return
1033
1034
    this.isShown = false
1035
1036
    this.escape()
1037
    this.resize()
1038
1039
    $(document).off('focusin.bs.modal')
1040
1041
    this.$element
1042
      .removeClass('in')
1043
      .off('click.dismiss.bs.modal')
1044
      .off('mouseup.dismiss.bs.modal')
1045
1046
    this.$dialog.off('mousedown.dismiss.bs.modal')
1047
1048
    $.support.transition && this.$element.hasClass('fade') ?
1049
      this.$element
1050
        .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1051
        .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1052
      this.hideModal()
1053
  }
1054
1055
  Modal.prototype.enforceFocus = function () {
1056
    $(document)
1057
      .off('focusin.bs.modal') // guard against infinite focus loop
1058
      .on('focusin.bs.modal', $.proxy(function (e) {
1059
        if (document !== e.target &&
1060
            this.$element[0] !== e.target &&
1061
            !this.$element.has(e.target).length) {
1062
          this.$element.trigger('focus')
1063
        }
1064
      }, this))
1065
  }
1066
1067
  Modal.prototype.escape = function () {
1068
    if (this.isShown && this.options.keyboard) {
1069
      this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
1070
        e.which == 27 && this.hide()
1071
      }, this))
1072
    } else if (!this.isShown) {
1073
      this.$element.off('keydown.dismiss.bs.modal')
1074
    }
1075
  }
1076
1077
  Modal.prototype.resize = function () {
1078
    if (this.isShown) {
1079
      $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this))
1080
    } else {
1081
      $(window).off('resize.bs.modal')
1082
    }
1083
  }
1084
1085
  Modal.prototype.hideModal = function () {
1086
    var that = this
1087
    this.$element.hide()
1088
    this.backdrop(function () {
1089
      that.$body.removeClass('modal-open')
1090
      that.resetAdjustments()
1091
      that.resetScrollbar()
1092
      that.$element.trigger('hidden.bs.modal')
1093
    })
1094
  }
1095
1096
  Modal.prototype.removeBackdrop = function () {
1097
    this.$backdrop && this.$backdrop.remove()
1098
    this.$backdrop = null
1099
  }
1100
1101
  Modal.prototype.backdrop = function (callback) {
1102
    var that = this
1103
    var animate = this.$element.hasClass('fade') ? 'fade' : ''
1104
1105
    if (this.isShown && this.options.backdrop) {
1106
      var doAnimate = $.support.transition && animate
1107
1108
      this.$backdrop = $(document.createElement('div'))
1109
        .addClass('modal-backdrop ' + animate)
1110
        .appendTo(this.$body)
1111
1112
      this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
1113
        if (this.ignoreBackdropClick) {
1114
          this.ignoreBackdropClick = false
1115
          return
1116
        }
1117
        if (e.target !== e.currentTarget) return
1118
        this.options.backdrop == 'static'
1119
          ? this.$element[0].focus()
1120
          : this.hide()
1121
      }, this))
1122
1123
      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
1124
1125
      this.$backdrop.addClass('in')
1126
1127
      if (!callback) return
1128
1129
      doAnimate ?
1130
        this.$backdrop
1131
          .one('bsTransitionEnd', callback)
1132
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1133
        callback()
1134
1135
    } else if (!this.isShown && this.$backdrop) {
1136
      this.$backdrop.removeClass('in')
1137
1138
      var callbackRemove = function () {
1139
        that.removeBackdrop()
1140
        callback && callback()
1141
      }
1142
      $.support.transition && this.$element.hasClass('fade') ?
1143
        this.$backdrop
1144
          .one('bsTransitionEnd', callbackRemove)
1145
          .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1146
        callbackRemove()
1147
1148
    } else if (callback) {
1149
      callback()
1150
    }
1151
  }
1152
1153
  // these following methods are used to handle overflowing modals
1154
1155
  Modal.prototype.handleUpdate = function () {
1156
    this.adjustDialog()
1157
  }
1158
1159
  Modal.prototype.adjustDialog = function () {
1160
    var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight
1161
1162
    this.$element.css({
1163
      paddingLeft:  !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '',
1164
      paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ''
1165
    })
1166
  }
1167
1168
  Modal.prototype.resetAdjustments = function () {
1169
    this.$element.css({
1170
      paddingLeft: '',
1171
      paddingRight: ''
1172
    })
1173
  }
1174
1175
  Modal.prototype.checkScrollbar = function () {
1176
    var fullWindowWidth = window.innerWidth
1177
    if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8
1178
      var documentElementRect = document.documentElement.getBoundingClientRect()
1179
      fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left)
1180
    }
1181
    this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth
1182
    this.scrollbarWidth = this.measureScrollbar()
1183
  }
1184
1185
  Modal.prototype.setScrollbar = function () {
1186
    var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
1187
    this.originalBodyPad = document.body.style.paddingRight || ''
1188
    if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
1189
  }
1190
1191
  Modal.prototype.resetScrollbar = function () {
1192
    this.$body.css('padding-right', this.originalBodyPad)
1193
  }
1194
1195
  Modal.prototype.measureScrollbar = function () { // thx walsh
1196
    var scrollDiv = document.createElement('div')
1197
    scrollDiv.className = 'modal-scrollbar-measure'
1198
    this.$body.append(scrollDiv)
1199
    var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
1200
    this.$body[0].removeChild(scrollDiv)
1201
    return scrollbarWidth
1202
  }
1203
1204
1205
  // MODAL PLUGIN DEFINITION
1206
  // =======================
1207
1208
  function Plugin(option, _relatedTarget) {
1209
    return this.each(function () {
1210
      var $this   = $(this)
1211
      var data    = $this.data('bs.modal')
1212
      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
1213
1214
      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
1215
      if (typeof option == 'string') data[option](_relatedTarget)
1216
      else if (options.show) data.show(_relatedTarget)
1217
    })
1218
  }
1219
1220
  var old = $.fn.modal
1221
1222
  $.fn.modal             = Plugin
1223
  $.fn.modal.Constructor = Modal
1224
1225
1226
  // MODAL NO CONFLICT
1227
  // =================
1228
1229
  $.fn.modal.noConflict = function () {
1230
    $.fn.modal = old
1231
    return this
1232
  }
1233
1234
1235
  // MODAL DATA-API
1236
  // ==============
1237
1238
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
1239
    var $this   = $(this)
1240
    var href    = $this.attr('href')
1241
    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
1242
    var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
1243
1244
    if ($this.is('a')) e.preventDefault()
1245
1246
    $target.one('show.bs.modal', function (showEvent) {
1247
      if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
1248
      $target.one('hidden.bs.modal', function () {
1249
        $this.is(':visible') && $this.trigger('focus')
1250
      })
1251
    })
1252
    Plugin.call($target, option, this)
1253
  })
1254
1255
}(jQuery);
1256
1257
/* ========================================================================
1258
 * Bootstrap: tooltip.js v3.3.7
1259
 * http://getbootstrap.com/javascript/#tooltip
1260
 * Inspired by the original jQuery.tipsy by Jason Frame
1261
 * ========================================================================
1262
 * Copyright 2011-2016 Twitter, Inc.
1263
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1264
 * ======================================================================== */
1265
1266
1267
+function ($) {
1268
  'use strict';
1269
1270
  // TOOLTIP PUBLIC CLASS DEFINITION
1271
  // ===============================
1272
1273
  var Tooltip = function (element, options) {
1274
    this.type       = null
1275
    this.options    = null
1276
    this.enabled    = null
1277
    this.timeout    = null
1278
    this.hoverState = null
1279
    this.$element   = null
1280
    this.inState    = null
1281
1282
    this.init('tooltip', element, options)
1283
  }
1284
1285
  Tooltip.VERSION  = '3.3.7'
1286
1287
  Tooltip.TRANSITION_DURATION = 150
1288
1289
  Tooltip.DEFAULTS = {
1290
    animation: true,
1291
    placement: 'top',
1292
    selector: false,
1293
    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
1294
    trigger: 'hover focus',
1295
    title: '',
1296
    delay: 0,
1297
    html: false,
1298
    container: false,
1299
    viewport: {
1300
      selector: 'body',
1301
      padding: 0
1302
    }
1303
  }
1304
1305
  Tooltip.prototype.init = function (type, element, options) {
1306
    this.enabled   = true
1307
    this.type      = type
1308
    this.$element  = $(element)
1309
    this.options   = this.getOptions(options)
1310
    this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
1311
    this.inState   = { click: false, hover: false, focus: false }
1312
1313
    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
1314
      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
1315
    }
1316
1317
    var triggers = this.options.trigger.split(' ')
1318
1319
    for (var i = triggers.length; i--;) {
1320
      var trigger = triggers[i]
1321
1322
      if (trigger == 'click') {
1323
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
1324
      } else if (trigger != 'manual') {
1325
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
1326
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
1327
1328
        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
1329
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
1330
      }
1331
    }
1332
1333
    this.options.selector ?
1334
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
1335
      this.fixTitle()
1336
  }
1337
1338
  Tooltip.prototype.getDefaults = function () {
1339
    return Tooltip.DEFAULTS
1340
  }
1341
1342
  Tooltip.prototype.getOptions = function (options) {
1343
    options = $.extend({}, this.getDefaults(), this.$element.data(), options)
1344
1345
    if (options.delay && typeof options.delay == 'number') {
1346
      options.delay = {
1347
        show: options.delay,
1348
        hide: options.delay
1349
      }
1350
    }
1351
1352
    return options
1353
  }
1354
1355
  Tooltip.prototype.getDelegateOptions = function () {
1356
    var options  = {}
1357
    var defaults = this.getDefaults()
1358
1359
    this._options && $.each(this._options, function (key, value) {
1360
      if (defaults[key] != value) options[key] = value
1361
    })
1362
1363
    return options
1364
  }
1365
1366
  Tooltip.prototype.enter = function (obj) {
1367
    var self = obj instanceof this.constructor ?
1368
      obj : $(obj.currentTarget).data('bs.' + this.type)
1369
1370
    if (!self) {
1371
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1372
      $(obj.currentTarget).data('bs.' + this.type, self)
1373
    }
1374
1375
    if (obj instanceof $.Event) {
1376
      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
1377
    }
1378
1379
    if (self.tip().hasClass('in') || self.hoverState == 'in') {
1380
      self.hoverState = 'in'
1381
      return
1382
    }
1383
1384
    clearTimeout(self.timeout)
1385
1386
    self.hoverState = 'in'
1387
1388
    if (!self.options.delay || !self.options.delay.show) return self.show()
1389
1390
    self.timeout = setTimeout(function () {
1391
      if (self.hoverState == 'in') self.show()
1392
    }, self.options.delay.show)
1393
  }
1394
1395
  Tooltip.prototype.isInStateTrue = function () {
1396
    for (var key in this.inState) {
0 ignored issues
show
Complexity introduced by
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
1397
      if (this.inState[key]) return true
1398
    }
1399
1400
    return false
1401
  }
1402
1403
  Tooltip.prototype.leave = function (obj) {
1404
    var self = obj instanceof this.constructor ?
1405
      obj : $(obj.currentTarget).data('bs.' + this.type)
1406
1407
    if (!self) {
1408
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
1409
      $(obj.currentTarget).data('bs.' + this.type, self)
1410
    }
1411
1412
    if (obj instanceof $.Event) {
1413
      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
1414
    }
1415
1416
    if (self.isInStateTrue()) return
1417
1418
    clearTimeout(self.timeout)
1419
1420
    self.hoverState = 'out'
1421
1422
    if (!self.options.delay || !self.options.delay.hide) return self.hide()
1423
1424
    self.timeout = setTimeout(function () {
1425
      if (self.hoverState == 'out') self.hide()
1426
    }, self.options.delay.hide)
1427
  }
1428
1429
  Tooltip.prototype.show = function () {
1430
    var e = $.Event('show.bs.' + this.type)
1431
1432
    if (this.hasContent() && this.enabled) {
1433
      this.$element.trigger(e)
1434
1435
      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1436
      if (e.isDefaultPrevented() || !inDom) return
1437
      var that = this
1438
1439
      var $tip = this.tip()
1440
1441
      var tipId = this.getUID(this.type)
1442
1443
      this.setContent()
1444
      $tip.attr('id', tipId)
1445
      this.$element.attr('aria-describedby', tipId)
1446
1447
      if (this.options.animation) $tip.addClass('fade')
1448
1449
      var placement = typeof this.options.placement == 'function' ?
1450
        this.options.placement.call(this, $tip[0], this.$element[0]) :
1451
        this.options.placement
1452
1453
      var autoToken = /\s?auto?\s?/i
1454
      var autoPlace = autoToken.test(placement)
1455
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
1456
1457
      $tip
1458
        .detach()
1459
        .css({ top: 0, left: 0, display: 'block' })
1460
        .addClass(placement)
1461
        .data('bs.' + this.type, this)
1462
1463
      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
1464
      this.$element.trigger('inserted.bs.' + this.type)
1465
1466
      var pos          = this.getPosition()
1467
      var actualWidth  = $tip[0].offsetWidth
1468
      var actualHeight = $tip[0].offsetHeight
1469
1470
      if (autoPlace) {
1471
        var orgPlacement = placement
1472
        var viewportDim = this.getPosition(this.$viewport)
1473
1474
        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
1475
                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
1476
                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
1477
                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
1478
                    placement
1479
1480
        $tip
1481
          .removeClass(orgPlacement)
1482
          .addClass(placement)
1483
      }
1484
1485
      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1486
1487
      this.applyPlacement(calculatedOffset, placement)
1488
1489
      var complete = function () {
1490
        var prevHoverState = that.hoverState
1491
        that.$element.trigger('shown.bs.' + that.type)
1492
        that.hoverState = null
1493
1494
        if (prevHoverState == 'out') that.leave(that)
1495
      }
1496
1497
      $.support.transition && this.$tip.hasClass('fade') ?
1498
        $tip
1499
          .one('bsTransitionEnd', complete)
1500
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1501
        complete()
1502
    }
1503
  }
1504
1505
  Tooltip.prototype.applyPlacement = function (offset, placement) {
1506
    var $tip   = this.tip()
1507
    var width  = $tip[0].offsetWidth
1508
    var height = $tip[0].offsetHeight
1509
1510
    // manually read margins because getBoundingClientRect includes difference
1511
    var marginTop = parseInt($tip.css('margin-top'), 10)
1512
    var marginLeft = parseInt($tip.css('margin-left'), 10)
1513
1514
    // we must check for NaN for ie 8/9
1515
    if (isNaN(marginTop))  marginTop  = 0
1516
    if (isNaN(marginLeft)) marginLeft = 0
1517
1518
    offset.top  += marginTop
1519
    offset.left += marginLeft
1520
1521
    // $.fn.offset doesn't round pixel values
1522
    // so we use setOffset directly with our own function B-0
1523
    $.offset.setOffset($tip[0], $.extend({
1524
      using: function (props) {
1525
        $tip.css({
1526
          top: Math.round(props.top),
1527
          left: Math.round(props.left)
1528
        })
1529
      }
1530
    }, offset), 0)
1531
1532
    $tip.addClass('in')
1533
1534
    // check to see if placing tip in new offset caused the tip to resize itself
1535
    var actualWidth  = $tip[0].offsetWidth
1536
    var actualHeight = $tip[0].offsetHeight
1537
1538
    if (placement == 'top' && actualHeight != height) {
1539
      offset.top = offset.top + height - actualHeight
1540
    }
1541
1542
    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1543
1544
    if (delta.left) offset.left += delta.left
1545
    else offset.top += delta.top
1546
1547
    var isVertical          = /top|bottom/.test(placement)
1548
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
1549
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
1550
1551
    $tip.offset(offset)
1552
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1553
  }
1554
1555
  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
1556
    this.arrow()
1557
      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
1558
      .css(isVertical ? 'top' : 'left', '')
1559
  }
1560
1561
  Tooltip.prototype.setContent = function () {
1562
    var $tip  = this.tip()
1563
    var title = this.getTitle()
1564
1565
    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
1566
    $tip.removeClass('fade in top bottom left right')
1567
  }
1568
1569
  Tooltip.prototype.hide = function (callback) {
1570
    var that = this
1571
    var $tip = $(this.$tip)
1572
    var e    = $.Event('hide.bs.' + this.type)
1573
1574
    function complete() {
1575
      if (that.hoverState != 'in') $tip.detach()
1576
      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
1577
        that.$element
1578
          .removeAttr('aria-describedby')
1579
          .trigger('hidden.bs.' + that.type)
1580
      }
1581
      callback && callback()
1582
    }
1583
1584
    this.$element.trigger(e)
1585
1586
    if (e.isDefaultPrevented()) return
1587
1588
    $tip.removeClass('in')
1589
1590
    $.support.transition && $tip.hasClass('fade') ?
1591
      $tip
1592
        .one('bsTransitionEnd', complete)
1593
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1594
      complete()
1595
1596
    this.hoverState = null
1597
1598
    return this
1599
  }
1600
1601
  Tooltip.prototype.fixTitle = function () {
1602
    var $e = this.$element
1603
    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
1604
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1605
    }
1606
  }
1607
1608
  Tooltip.prototype.hasContent = function () {
1609
    return this.getTitle()
1610
  }
1611
1612
  Tooltip.prototype.getPosition = function ($element) {
1613
    $element   = $element || this.$element
1614
1615
    var el     = $element[0]
1616
    var isBody = el.tagName == 'BODY'
1617
1618
    var elRect    = el.getBoundingClientRect()
1619
    if (elRect.width == null) {
1620
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
1621
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
1622
    }
1623
    var isSvg = window.SVGElement && el instanceof window.SVGElement
1624
    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
1625
    // See https://github.com/twbs/bootstrap/issues/20280
1626
    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
1627
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
1628
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
1629
1630
    return $.extend({}, elRect, scroll, outerDims, elOffset)
1631
  }
1632
1633
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
1634
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
1635
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1636
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1637
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
1638
1639
  }
1640
1641
  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
1642
    var delta = { top: 0, left: 0 }
1643
    if (!this.$viewport) return delta
1644
1645
    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
1646
    var viewportDimensions = this.getPosition(this.$viewport)
1647
1648
    if (/right|left/.test(placement)) {
1649
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
1650
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
1651
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
1652
        delta.top = viewportDimensions.top - topEdgeOffset
1653
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
1654
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
1655
      }
1656
    } else {
1657
      var leftEdgeOffset  = pos.left - viewportPadding
1658
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
1659
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
1660
        delta.left = viewportDimensions.left - leftEdgeOffset
1661
      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
1662
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
1663
      }
1664
    }
1665
1666
    return delta
1667
  }
1668
1669
  Tooltip.prototype.getTitle = function () {
1670
    var title
1671
    var $e = this.$element
1672
    var o  = this.options
1673
1674
    title = $e.attr('data-original-title')
1675
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
1676
1677
    return title
1678
  }
1679
1680
  Tooltip.prototype.getUID = function (prefix) {
1681
    do prefix += ~~(Math.random() * 1000000)
1682
    while (document.getElementById(prefix))
1683
    return prefix
1684
  }
1685
1686
  Tooltip.prototype.tip = function () {
1687
    if (!this.$tip) {
1688
      this.$tip = $(this.options.template)
1689
      if (this.$tip.length != 1) {
1690
        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
1691
      }
1692
    }
1693
    return this.$tip
1694
  }
1695
1696
  Tooltip.prototype.arrow = function () {
1697
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1698
  }
1699
1700
  Tooltip.prototype.enable = function () {
1701
    this.enabled = true
1702
  }
1703
1704
  Tooltip.prototype.disable = function () {
1705
    this.enabled = false
1706
  }
1707
1708
  Tooltip.prototype.toggleEnabled = function () {
1709
    this.enabled = !this.enabled
1710
  }
1711
1712
  Tooltip.prototype.toggle = function (e) {
1713
    var self = this
1714
    if (e) {
1715
      self = $(e.currentTarget).data('bs.' + this.type)
1716
      if (!self) {
1717
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
1718
        $(e.currentTarget).data('bs.' + this.type, self)
1719
      }
1720
    }
1721
1722
    if (e) {
1723
      self.inState.click = !self.inState.click
1724
      if (self.isInStateTrue()) self.enter(self)
1725
      else self.leave(self)
1726
    } else {
1727
      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1728
    }
1729
  }
1730
1731
  Tooltip.prototype.destroy = function () {
1732
    var that = this
1733
    clearTimeout(this.timeout)
1734
    this.hide(function () {
1735
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
1736
      if (that.$tip) {
1737
        that.$tip.detach()
1738
      }
1739
      that.$tip = null
1740
      that.$arrow = null
1741
      that.$viewport = null
1742
      that.$element = null
1743
    })
1744
  }
1745
1746
1747
  // TOOLTIP PLUGIN DEFINITION
1748
  // =========================
1749
1750 View Code Duplication
  function Plugin(option) {
1751
    return this.each(function () {
1752
      var $this   = $(this)
1753
      var data    = $this.data('bs.tooltip')
1754
      var options = typeof option == 'object' && option
1755
1756
      if (!data && /destroy|hide/.test(option)) return
1757
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
1758
      if (typeof option == 'string') data[option]()
1759
    })
1760
  }
1761
1762
  var old = $.fn.tooltip
1763
1764
  $.fn.tooltip             = Plugin
1765
  $.fn.tooltip.Constructor = Tooltip
1766
1767
1768
  // TOOLTIP NO CONFLICT
1769
  // ===================
1770
1771
  $.fn.tooltip.noConflict = function () {
1772
    $.fn.tooltip = old
1773
    return this
1774
  }
1775
1776
}(jQuery);
1777
1778
/* ========================================================================
1779
 * Bootstrap: popover.js v3.3.7
1780
 * http://getbootstrap.com/javascript/#popovers
1781
 * ========================================================================
1782
 * Copyright 2011-2016 Twitter, Inc.
1783
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1784
 * ======================================================================== */
1785
1786
1787
+function ($) {
1788
  'use strict';
1789
1790
  // POPOVER PUBLIC CLASS DEFINITION
1791
  // ===============================
1792
1793
  var Popover = function (element, options) {
1794
    this.init('popover', element, options)
1795
  }
1796
1797
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1798
1799
  Popover.VERSION  = '3.3.7'
1800
1801
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
1802
    placement: 'right',
1803
    trigger: 'click',
1804
    content: '',
1805
    template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
1806
  })
1807
1808
1809
  // NOTE: POPOVER EXTENDS tooltip.js
1810
  // ================================
1811
1812
  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
1813
1814
  Popover.prototype.constructor = Popover
1815
1816
  Popover.prototype.getDefaults = function () {
1817
    return Popover.DEFAULTS
1818
  }
1819
1820
  Popover.prototype.setContent = function () {
1821
    var $tip    = this.tip()
1822
    var title   = this.getTitle()
1823
    var content = this.getContent()
1824
1825
    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1826
    $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
1827
      this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
1828
    ](content)
1829
1830
    $tip.removeClass('fade top bottom left right in')
1831
1832
    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
1833
    // this manually by checking the contents.
1834
    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
1835
  }
1836
1837
  Popover.prototype.hasContent = function () {
1838
    return this.getTitle() || this.getContent()
1839
  }
1840
1841
  Popover.prototype.getContent = function () {
1842
    var $e = this.$element
1843
    var o  = this.options
1844
1845
    return $e.attr('data-content')
1846
      || (typeof o.content == 'function' ?
1847
            o.content.call($e[0]) :
1848
            o.content)
1849
  }
1850
1851
  Popover.prototype.arrow = function () {
1852
    return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1853
  }
1854
1855
1856
  // POPOVER PLUGIN DEFINITION
1857
  // =========================
1858
1859 View Code Duplication
  function Plugin(option) {
1860
    return this.each(function () {
1861
      var $this   = $(this)
1862
      var data    = $this.data('bs.popover')
1863
      var options = typeof option == 'object' && option
1864
1865
      if (!data && /destroy|hide/.test(option)) return
1866
      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
1867
      if (typeof option == 'string') data[option]()
1868
    })
1869
  }
1870
1871
  var old = $.fn.popover
1872
1873
  $.fn.popover             = Plugin
1874
  $.fn.popover.Constructor = Popover
1875
1876
1877
  // POPOVER NO CONFLICT
1878
  // ===================
1879
1880
  $.fn.popover.noConflict = function () {
1881
    $.fn.popover = old
1882
    return this
1883
  }
1884
1885
}(jQuery);
1886
1887
/* ========================================================================
1888
 * Bootstrap: scrollspy.js v3.3.7
1889
 * http://getbootstrap.com/javascript/#scrollspy
1890
 * ========================================================================
1891
 * Copyright 2011-2016 Twitter, Inc.
1892
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1893
 * ======================================================================== */
1894
1895
1896
+function ($) {
1897
  'use strict';
1898
1899
  // SCROLLSPY CLASS DEFINITION
1900
  // ==========================
1901
1902
  function ScrollSpy(element, options) {
1903
    this.$body          = $(document.body)
1904
    this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
1905
    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
1906
    this.selector       = (this.options.target || '') + ' .nav li > a'
1907
    this.offsets        = []
1908
    this.targets        = []
1909
    this.activeTarget   = null
1910
    this.scrollHeight   = 0
1911
1912
    this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
1913
    this.refresh()
1914
    this.process()
1915
  }
1916
1917
  ScrollSpy.VERSION  = '3.3.7'
1918
1919
  ScrollSpy.DEFAULTS = {
1920
    offset: 10
1921
  }
1922
1923
  ScrollSpy.prototype.getScrollHeight = function () {
1924
    return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
1925
  }
1926
1927
  ScrollSpy.prototype.refresh = function () {
1928
    var that          = this
1929
    var offsetMethod  = 'offset'
1930
    var offsetBase    = 0
1931
1932
    this.offsets      = []
1933
    this.targets      = []
1934
    this.scrollHeight = this.getScrollHeight()
1935
1936
    if (!$.isWindow(this.$scrollElement[0])) {
1937
      offsetMethod = 'position'
1938
      offsetBase   = this.$scrollElement.scrollTop()
1939
    }
1940
1941
    this.$body
1942
      .find(this.selector)
1943
      .map(function () {
1944
        var $el   = $(this)
1945
        var href  = $el.data('target') || $el.attr('href')
1946
        var $href = /^#./.test(href) && $(href)
1947
1948
        return ($href
1949
          && $href.length
1950
          && $href.is(':visible')
1951
          && [[$href[offsetMethod]().top + offsetBase, href]]) || null
1952
      })
1953
      .sort(function (a, b) { return a[0] - b[0] })
1954
      .each(function () {
1955
        that.offsets.push(this[0])
1956
        that.targets.push(this[1])
1957
      })
1958
  }
1959
1960
  ScrollSpy.prototype.process = function () {
1961
    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
1962
    var scrollHeight = this.getScrollHeight()
1963
    var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
1964
    var offsets      = this.offsets
1965
    var targets      = this.targets
1966
    var activeTarget = this.activeTarget
1967
    var i
1968
1969
    if (this.scrollHeight != scrollHeight) {
1970
      this.refresh()
1971
    }
1972
1973
    if (scrollTop >= maxScroll) {
1974
      return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
1975
    }
1976
1977
    if (activeTarget && scrollTop < offsets[0]) {
1978
      this.activeTarget = null
1979
      return this.clear()
1980
    }
1981
1982
    for (i = offsets.length; i--;) {
1983
      activeTarget != targets[i]
1984
        && scrollTop >= offsets[i]
1985
        && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
1986
        && this.activate(targets[i])
1987
    }
1988
  }
1989
1990
  ScrollSpy.prototype.activate = function (target) {
1991
    this.activeTarget = target
1992
1993
    this.clear()
1994
1995
    var selector = this.selector +
1996
      '[data-target="' + target + '"],' +
1997
      this.selector + '[href="' + target + '"]'
1998
1999
    var active = $(selector)
2000
      .parents('li')
2001
      .addClass('active')
2002
2003
    if (active.parent('.dropdown-menu').length) {
2004
      active = active
2005
        .closest('li.dropdown')
2006
        .addClass('active')
2007
    }
2008
2009
    active.trigger('activate.bs.scrollspy')
2010
  }
2011
2012
  ScrollSpy.prototype.clear = function () {
2013
    $(this.selector)
2014
      .parentsUntil(this.options.target, '.active')
2015
      .removeClass('active')
2016
  }
2017
2018
2019
  // SCROLLSPY PLUGIN DEFINITION
2020
  // ===========================
2021
2022
  function Plugin(option) {
2023
    return this.each(function () {
2024
      var $this   = $(this)
2025
      var data    = $this.data('bs.scrollspy')
2026
      var options = typeof option == 'object' && option
2027
2028
      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
2029
      if (typeof option == 'string') data[option]()
2030
    })
2031
  }
2032
2033
  var old = $.fn.scrollspy
2034
2035
  $.fn.scrollspy             = Plugin
2036
  $.fn.scrollspy.Constructor = ScrollSpy
2037
2038
2039
  // SCROLLSPY NO CONFLICT
2040
  // =====================
2041
2042
  $.fn.scrollspy.noConflict = function () {
2043
    $.fn.scrollspy = old
2044
    return this
2045
  }
2046
2047
2048
  // SCROLLSPY DATA-API
2049
  // ==================
2050
2051
  $(window).on('load.bs.scrollspy.data-api', function () {
2052
    $('[data-spy="scroll"]').each(function () {
2053
      var $spy = $(this)
2054
      Plugin.call($spy, $spy.data())
2055
    })
2056
  })
2057
2058
}(jQuery);
2059
2060
/* ========================================================================
2061
 * Bootstrap: tab.js v3.3.7
2062
 * http://getbootstrap.com/javascript/#tabs
2063
 * ========================================================================
2064
 * Copyright 2011-2016 Twitter, Inc.
2065
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2066
 * ======================================================================== */
2067
2068
2069
+function ($) {
2070
  'use strict';
2071
2072
  // TAB CLASS DEFINITION
2073
  // ====================
2074
2075
  var Tab = function (element) {
2076
    // jscs:disable requireDollarBeforejQueryAssignment
2077
    this.element = $(element)
2078
    // jscs:enable requireDollarBeforejQueryAssignment
2079
  }
2080
2081
  Tab.VERSION = '3.3.7'
2082
2083
  Tab.TRANSITION_DURATION = 150
2084
2085
  Tab.prototype.show = function () {
2086
    var $this    = this.element
2087
    var $ul      = $this.closest('ul:not(.dropdown-menu)')
2088
    var selector = $this.data('target')
2089
2090
    if (!selector) {
2091
      selector = $this.attr('href')
2092
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
2093
    }
2094
2095
    if ($this.parent('li').hasClass('active')) return
2096
2097
    var $previous = $ul.find('.active:last a')
2098
    var hideEvent = $.Event('hide.bs.tab', {
2099
      relatedTarget: $this[0]
2100
    })
2101
    var showEvent = $.Event('show.bs.tab', {
2102
      relatedTarget: $previous[0]
2103
    })
2104
2105
    $previous.trigger(hideEvent)
2106
    $this.trigger(showEvent)
2107
2108
    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
2109
2110
    var $target = $(selector)
2111
2112
    this.activate($this.closest('li'), $ul)
2113
    this.activate($target, $target.parent(), function () {
2114
      $previous.trigger({
2115
        type: 'hidden.bs.tab',
2116
        relatedTarget: $this[0]
2117
      })
2118
      $this.trigger({
2119
        type: 'shown.bs.tab',
2120
        relatedTarget: $previous[0]
2121
      })
2122
    })
2123
  }
2124
2125
  Tab.prototype.activate = function (element, container, callback) {
2126
    var $active    = container.find('> .active')
2127
    var transition = callback
2128
      && $.support.transition
2129
      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
2130
2131
    function next() {
2132
      $active
2133
        .removeClass('active')
2134
        .find('> .dropdown-menu > .active')
2135
          .removeClass('active')
2136
        .end()
2137
        .find('[data-toggle="tab"]')
2138
          .attr('aria-expanded', false)
2139
2140
      element
2141
        .addClass('active')
2142
        .find('[data-toggle="tab"]')
2143
          .attr('aria-expanded', true)
2144
2145
      if (transition) {
2146
        element[0].offsetWidth // reflow for transition
0 ignored issues
show
introduced by
The result of the property access to element.0.offsetWidth is not used.
Loading history...
2147
        element.addClass('in')
2148
      } else {
2149
        element.removeClass('fade')
2150
      }
2151
2152
      if (element.parent('.dropdown-menu').length) {
2153
        element
2154
          .closest('li.dropdown')
2155
            .addClass('active')
2156
          .end()
2157
          .find('[data-toggle="tab"]')
2158
            .attr('aria-expanded', true)
2159
      }
2160
2161
      callback && callback()
2162
    }
2163
2164
    $active.length && transition ?
2165
      $active
2166
        .one('bsTransitionEnd', next)
2167
        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
2168
      next()
2169
2170
    $active.removeClass('in')
2171
  }
2172
2173
2174
  // TAB PLUGIN DEFINITION
2175
  // =====================
2176
2177
  function Plugin(option) {
2178
    return this.each(function () {
2179
      var $this = $(this)
2180
      var data  = $this.data('bs.tab')
2181
2182
      if (!data) $this.data('bs.tab', (data = new Tab(this)))
2183
      if (typeof option == 'string') data[option]()
2184
    })
2185
  }
2186
2187
  var old = $.fn.tab
2188
2189
  $.fn.tab             = Plugin
2190
  $.fn.tab.Constructor = Tab
2191
2192
2193
  // TAB NO CONFLICT
2194
  // ===============
2195
2196
  $.fn.tab.noConflict = function () {
2197
    $.fn.tab = old
2198
    return this
2199
  }
2200
2201
2202
  // TAB DATA-API
2203
  // ============
2204
2205
  var clickHandler = function (e) {
2206
    e.preventDefault()
2207
    Plugin.call($(this), 'show')
2208
  }
2209
2210
  $(document)
2211
    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
2212
    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
2213
2214
}(jQuery);
2215
2216
/* ========================================================================
2217
 * Bootstrap: affix.js v3.3.7
2218
 * http://getbootstrap.com/javascript/#affix
2219
 * ========================================================================
2220
 * Copyright 2011-2016 Twitter, Inc.
2221
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
2222
 * ======================================================================== */
2223
2224
2225
+function ($) {
2226
  'use strict';
2227
2228
  // AFFIX CLASS DEFINITION
2229
  // ======================
2230
2231
  var Affix = function (element, options) {
2232
    this.options = $.extend({}, Affix.DEFAULTS, options)
2233
2234
    this.$target = $(this.options.target)
2235
      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
2236
      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
2237
2238
    this.$element     = $(element)
2239
    this.affixed      = null
2240
    this.unpin        = null
2241
    this.pinnedOffset = null
2242
2243
    this.checkPosition()
2244
  }
2245
2246
  Affix.VERSION  = '3.3.7'
2247
2248
  Affix.RESET    = 'affix affix-top affix-bottom'
2249
2250
  Affix.DEFAULTS = {
2251
    offset: 0,
2252
    target: window
2253
  }
2254
2255
  Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) {
2256
    var scrollTop    = this.$target.scrollTop()
2257
    var position     = this.$element.offset()
2258
    var targetHeight = this.$target.height()
2259
2260
    if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false
2261
2262
    if (this.affixed == 'bottom') {
2263
      if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom'
2264
      return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom'
2265
    }
2266
2267
    var initializing   = this.affixed == null
2268
    var colliderTop    = initializing ? scrollTop : position.top
2269
    var colliderHeight = initializing ? targetHeight : height
2270
2271
    if (offsetTop != null && scrollTop <= offsetTop) return 'top'
2272
    if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom'
2273
2274
    return false
2275
  }
2276
2277
  Affix.prototype.getPinnedOffset = function () {
2278
    if (this.pinnedOffset) return this.pinnedOffset
2279
    this.$element.removeClass(Affix.RESET).addClass('affix')
2280
    var scrollTop = this.$target.scrollTop()
2281
    var position  = this.$element.offset()
2282
    return (this.pinnedOffset = position.top - scrollTop)
2283
  }
2284
2285
  Affix.prototype.checkPositionWithEventLoop = function () {
2286
    setTimeout($.proxy(this.checkPosition, this), 1)
2287
  }
2288
2289
  Affix.prototype.checkPosition = function () {
2290
    if (!this.$element.is(':visible')) return
2291
2292
    var height       = this.$element.height()
2293
    var offset       = this.options.offset
2294
    var offsetTop    = offset.top
2295
    var offsetBottom = offset.bottom
2296
    var scrollHeight = Math.max($(document).height(), $(document.body).height())
2297
2298
    if (typeof offset != 'object')         offsetBottom = offsetTop = offset
2299
    if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
2300
    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
2301
2302
    var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom)
2303
2304
    if (this.affixed != affix) {
2305
      if (this.unpin != null) this.$element.css('top', '')
2306
2307
      var affixType = 'affix' + (affix ? '-' + affix : '')
2308
      var e         = $.Event(affixType + '.bs.affix')
2309
2310
      this.$element.trigger(e)
2311
2312
      if (e.isDefaultPrevented()) return
2313
2314
      this.affixed = affix
2315
      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
2316
2317
      this.$element
2318
        .removeClass(Affix.RESET)
2319
        .addClass(affixType)
2320
        .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2321
    }
2322
2323
    if (affix == 'bottom') {
2324
      this.$element.offset({
2325
        top: scrollHeight - height - offsetBottom
2326
      })
2327
    }
2328
  }
2329
2330
2331
  // AFFIX PLUGIN DEFINITION
2332
  // =======================
2333
2334
  function Plugin(option) {
2335
    return this.each(function () {
2336
      var $this   = $(this)
2337
      var data    = $this.data('bs.affix')
2338
      var options = typeof option == 'object' && option
2339
2340
      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
2341
      if (typeof option == 'string') data[option]()
2342
    })
2343
  }
2344
2345
  var old = $.fn.affix
2346
2347
  $.fn.affix             = Plugin
2348
  $.fn.affix.Constructor = Affix
2349
2350
2351
  // AFFIX NO CONFLICT
2352
  // =================
2353
2354
  $.fn.affix.noConflict = function () {
2355
    $.fn.affix = old
2356
    return this
2357
  }
2358
2359
2360
  // AFFIX DATA-API
2361
  // ==============
2362
2363
  $(window).on('load', function () {
2364
    $('[data-spy="affix"]').each(function () {
2365
      var $spy = $(this)
2366
      var data = $spy.data()
2367
2368
      data.offset = data.offset || {}
2369
2370
      if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2371
      if (data.offsetTop    != null) data.offset.top    = data.offsetTop
2372
2373
      Plugin.call($spy, data)
2374
    })
2375
  })
2376
2377
}(jQuery);
2378