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