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