statements 0.1.0

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