weeler 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d993ac60b9d9f338a01a5c51836b905e86928e0
4
- data.tar.gz: 015863705f2c4761a02ff6cecb710d2e36f3e2e7
3
+ metadata.gz: 03eddaf5ac0d212b379c93fd2c986bfd4039b7cd
4
+ data.tar.gz: fa40eed9d7d0507425b99da69fee6d33e3c98c32
5
5
  SHA512:
6
- metadata.gz: 85b6eeb35a6054b99706961f0276bd2836b763102962b2808f3119824d4a1d6eaad5af890d4c6fb5b1fdcc9c4a911dcf7ed6b10e4ddd8804992005e564d13bba
7
- data.tar.gz: dd7a5a7c0956b906cb8ae3eb9d53b1eedd91c284500f8a95f78704eae0c899b3ed67add13b787153f332383d9debc63d17c340092fb12795a24f47bbe76d2535
6
+ metadata.gz: 7e582e3235a4e5833170055de3c4966fe90ad76b7de8768f70a8df6a14ff0049aa026057242097d5f5be1b126cb01165581d2d3cc1eea6a69cfce4b4e4309765
7
+ data.tar.gz: 0b78e231f7b9100d82eb61523bed40143cfe0b55dca0183f4f2b598cbaa624d80104432aea1b00a6a2438bdd3c08a3443dd3dddfc615ddd05942f7e869d2e411
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.0.3
2
+
3
+ ### Features & Enhancements
4
+
5
+ * Updated bootstrap to v3.3.1
6
+
7
+ ### Contributors
8
+
9
+ * Artis Raugulis
10
+
1
11
  ## 1.0.2
2
12
 
3
13
  ### Bug Fixes
@@ -1,24 +1,91 @@
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
+
1
78
  /* ========================================================================
2
- * Bootstrap: alert.js v3.0.0
3
- * http://twbs.github.com/bootstrap/javascript.html#alerts
79
+ * Bootstrap: alert.js v3.3.1
80
+ * http://getbootstrap.com/javascript/#alerts
4
81
  * ========================================================================
5
- * Copyright 2013 Twitter, Inc.
6
- *
7
- * Licensed under the Apache License, Version 2.0 (the "License");
8
- * you may not use this file except in compliance with the License.
9
- * You may obtain a copy of the License at
10
- *
11
- * http://www.apache.org/licenses/LICENSE-2.0
12
- *
13
- * Unless required by applicable law or agreed to in writing, software
14
- * distributed under the License is distributed on an "AS IS" BASIS,
15
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
- * See the License for the specific language governing permissions and
17
- * limitations under the License.
82
+ * Copyright 2011-2014 Twitter, Inc.
83
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
18
84
  * ======================================================================== */
19
85
 
20
86
 
21
- +function ($) { "use strict";
87
+ +function ($) {
88
+ 'use strict';
22
89
 
23
90
  // ALERT CLASS DEFINITION
24
91
  // ======================
@@ -28,6 +95,10 @@
28
95
  $(el).on('click', dismiss, this.close)
29
96
  }
30
97
 
98
+ Alert.VERSION = '3.3.1'
99
+
100
+ Alert.TRANSITION_DURATION = 150
101
+
31
102
  Alert.prototype.close = function (e) {
32
103
  var $this = $(this)
33
104
  var selector = $this.attr('data-target')
@@ -42,7 +113,7 @@
42
113
  if (e) e.preventDefault()
43
114
 
44
115
  if (!$parent.length) {
45
- $parent = $this.hasClass('alert') ? $this : $this.parent()
116
+ $parent = $this.closest('.alert')
46
117
  }
47
118
 
48
119
  $parent.trigger(e = $.Event('close.bs.alert'))
@@ -52,13 +123,14 @@
52
123
  $parent.removeClass('in')
53
124
 
54
125
  function removeElement() {
55
- $parent.trigger('closed.bs.alert').remove()
126
+ // detach from parent, fire event then clean up data
127
+ $parent.detach().trigger('closed.bs.alert').remove()
56
128
  }
57
129
 
58
130
  $.support.transition && $parent.hasClass('fade') ?
59
131
  $parent
60
- .one($.support.transition.end, removeElement)
61
- .emulateTransitionEnd(150) :
132
+ .one('bsTransitionEnd', removeElement)
133
+ .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
62
134
  removeElement()
63
135
  }
64
136
 
@@ -66,9 +138,7 @@
66
138
  // ALERT PLUGIN DEFINITION
67
139
  // =======================
68
140
 
69
- var old = $.fn.alert
70
-
71
- $.fn.alert = function (option) {
141
+ function Plugin(option) {
72
142
  return this.each(function () {
73
143
  var $this = $(this)
74
144
  var data = $this.data('bs.alert')
@@ -78,6 +148,9 @@
78
148
  })
79
149
  }
80
150
 
151
+ var old = $.fn.alert
152
+
153
+ $.fn.alert = Plugin
81
154
  $.fn.alert.Constructor = Alert
82
155
 
83
156
 
@@ -95,38 +168,31 @@
95
168
 
96
169
  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
97
170
 
98
- }(window.jQuery);
171
+ }(jQuery);
99
172
 
100
173
  /* ========================================================================
101
- * Bootstrap: button.js v3.0.0
102
- * http://twbs.github.com/bootstrap/javascript.html#buttons
174
+ * Bootstrap: button.js v3.3.1
175
+ * http://getbootstrap.com/javascript/#buttons
103
176
  * ========================================================================
104
- * Copyright 2013 Twitter, Inc.
105
- *
106
- * Licensed under the Apache License, Version 2.0 (the "License");
107
- * you may not use this file except in compliance with the License.
108
- * You may obtain a copy of the License at
109
- *
110
- * http://www.apache.org/licenses/LICENSE-2.0
111
- *
112
- * Unless required by applicable law or agreed to in writing, software
113
- * distributed under the License is distributed on an "AS IS" BASIS,
114
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115
- * See the License for the specific language governing permissions and
116
- * limitations under the License.
177
+ * Copyright 2011-2014 Twitter, Inc.
178
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
117
179
  * ======================================================================== */
118
180
 
119
181
 
120
- +function ($) { "use strict";
182
+ +function ($) {
183
+ 'use strict';
121
184
 
122
185
  // BUTTON PUBLIC CLASS DEFINITION
123
186
  // ==============================
124
187
 
125
188
  var Button = function (element, options) {
126
- this.$element = $(element)
127
- this.options = $.extend({}, Button.DEFAULTS, options)
189
+ this.$element = $(element)
190
+ this.options = $.extend({}, Button.DEFAULTS, options)
191
+ this.isLoading = false
128
192
  }
129
193
 
194
+ Button.VERSION = '3.3.1'
195
+
130
196
  Button.DEFAULTS = {
131
197
  loadingText: 'loading...'
132
198
  }
@@ -139,38 +205,45 @@
139
205
 
140
206
  state = state + 'Text'
141
207
 
142
- if (!data.resetText) $el.data('resetText', $el[val]())
143
-
144
- $el[val](data[state] || this.options[state])
208
+ if (data.resetText == null) $el.data('resetText', $el[val]())
145
209
 
146
210
  // push to event loop to allow forms to submit
147
- setTimeout(function () {
148
- state == 'loadingText' ?
149
- $el.addClass(d).attr(d, d) :
150
- $el.removeClass(d).removeAttr(d);
151
- }, 0)
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)
152
222
  }
153
223
 
154
224
  Button.prototype.toggle = function () {
225
+ var changed = true
155
226
  var $parent = this.$element.closest('[data-toggle="buttons"]')
156
227
 
157
228
  if ($parent.length) {
158
229
  var $input = this.$element.find('input')
159
- .prop('checked', !this.$element.hasClass('active'))
160
- .trigger('change')
161
- if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
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'))
162
237
  }
163
238
 
164
- this.$element.toggleClass('active')
239
+ if (changed) this.$element.toggleClass('active')
165
240
  }
166
241
 
167
242
 
168
243
  // BUTTON PLUGIN DEFINITION
169
244
  // ========================
170
245
 
171
- var old = $.fn.button
172
-
173
- $.fn.button = function (option) {
246
+ function Plugin(option) {
174
247
  return this.each(function () {
175
248
  var $this = $(this)
176
249
  var data = $this.data('bs.button')
@@ -183,6 +256,9 @@
183
256
  })
184
257
  }
185
258
 
259
+ var old = $.fn.button
260
+
261
+ $.fn.button = Plugin
186
262
  $.fn.button.Constructor = Button
187
263
 
188
264
 
@@ -198,36 +274,30 @@
198
274
  // BUTTON DATA-API
199
275
  // ===============
200
276
 
201
- $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
202
- var $btn = $(e.target)
203
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
204
- $btn.button('toggle')
205
- e.preventDefault()
206
- })
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
+ })
207
287
 
208
- }(window.jQuery);
288
+ }(jQuery);
209
289
 
210
290
  /* ========================================================================
211
- * Bootstrap: carousel.js v3.0.0
212
- * http://twbs.github.com/bootstrap/javascript.html#carousel
291
+ * Bootstrap: carousel.js v3.3.1
292
+ * http://getbootstrap.com/javascript/#carousel
213
293
  * ========================================================================
214
- * Copyright 2012 Twitter, Inc.
215
- *
216
- * Licensed under the Apache License, Version 2.0 (the "License");
217
- * you may not use this file except in compliance with the License.
218
- * You may obtain a copy of the License at
219
- *
220
- * http://www.apache.org/licenses/LICENSE-2.0
221
- *
222
- * Unless required by applicable law or agreed to in writing, software
223
- * distributed under the License is distributed on an "AS IS" BASIS,
224
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
225
- * See the License for the specific language governing permissions and
226
- * limitations under the License.
294
+ * Copyright 2011-2014 Twitter, Inc.
295
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
227
296
  * ======================================================================== */
228
297
 
229
298
 
230
- +function ($) { "use strict";
299
+ +function ($) {
300
+ 'use strict';
231
301
 
232
302
  // CAROUSEL CLASS DEFINITION
233
303
  // =========================
@@ -242,18 +312,36 @@
242
312
  this.$active =
243
313
  this.$items = null
244
314
 
245
- this.options.pause == 'hover' && this.$element
246
- .on('mouseenter', $.proxy(this.pause, this))
247
- .on('mouseleave', $.proxy(this.cycle, this))
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))
248
320
  }
249
321
 
322
+ Carousel.VERSION = '3.3.1'
323
+
324
+ Carousel.TRANSITION_DURATION = 600
325
+
250
326
  Carousel.DEFAULTS = {
251
- interval: 5000
252
- , pause: 'hover'
253
- , wrap: true
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()
254
342
  }
255
343
 
256
- Carousel.prototype.cycle = function (e) {
344
+ Carousel.prototype.cycle = function (e) {
257
345
  e || (this.paused = false)
258
346
 
259
347
  this.interval && clearInterval(this.interval)
@@ -265,29 +353,34 @@
265
353
  return this
266
354
  }
267
355
 
268
- Carousel.prototype.getActiveIndex = function () {
269
- this.$active = this.$element.find('.item.active')
270
- this.$items = this.$active.parent().children()
356
+ Carousel.prototype.getItemIndex = function (item) {
357
+ this.$items = item.parent().children('.item')
358
+ return this.$items.index(item || this.$active)
359
+ }
271
360
 
272
- return this.$items.index(this.$active)
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)
273
366
  }
274
367
 
275
368
  Carousel.prototype.to = function (pos) {
276
369
  var that = this
277
- var activeIndex = this.getActiveIndex()
370
+ var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
278
371
 
279
372
  if (pos > (this.$items.length - 1) || pos < 0) return
280
373
 
281
- if (this.sliding) return this.$element.one('slid', function () { that.to(pos) })
374
+ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
282
375
  if (activeIndex == pos) return this.pause().cycle()
283
376
 
284
- return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
377
+ return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos))
285
378
  }
286
379
 
287
380
  Carousel.prototype.pause = function (e) {
288
381
  e || (this.paused = true)
289
382
 
290
- if (this.$element.find('.next, .prev').length && $.support.transition.end) {
383
+ if (this.$element.find('.next, .prev').length && $.support.transition) {
291
384
  this.$element.trigger($.support.transition.end)
292
385
  this.cycle(true)
293
386
  }
@@ -309,7 +402,7 @@
309
402
 
310
403
  Carousel.prototype.slide = function (type, next) {
311
404
  var $active = this.$element.find('.item.active')
312
- var $next = next || $active[type]()
405
+ var $next = next || this.getItemForDirection(type, $active)
313
406
  var isCycling = this.interval
314
407
  var direction = type == 'next' ? 'left' : 'right'
315
408
  var fallback = type == 'next' ? 'first' : 'last'
@@ -320,44 +413,47 @@
320
413
  $next = this.$element.find('.item')[fallback]()
321
414
  }
322
415
 
323
- this.sliding = true
416
+ if ($next.hasClass('active')) return (this.sliding = false)
324
417
 
325
- isCycling && this.pause()
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
326
425
 
327
- var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })
426
+ this.sliding = true
328
427
 
329
- if ($next.hasClass('active')) return
428
+ isCycling && this.pause()
330
429
 
331
430
  if (this.$indicators.length) {
332
431
  this.$indicators.find('.active').removeClass('active')
333
- this.$element.one('slid', function () {
334
- var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
335
- $nextIndicator && $nextIndicator.addClass('active')
336
- })
432
+ var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
433
+ $nextIndicator && $nextIndicator.addClass('active')
337
434
  }
338
435
 
436
+ var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
339
437
  if ($.support.transition && this.$element.hasClass('slide')) {
340
- this.$element.trigger(e)
341
- if (e.isDefaultPrevented()) return
342
438
  $next.addClass(type)
343
439
  $next[0].offsetWidth // force reflow
344
440
  $active.addClass(direction)
345
441
  $next.addClass(direction)
346
442
  $active
347
- .one($.support.transition.end, function () {
443
+ .one('bsTransitionEnd', function () {
348
444
  $next.removeClass([type, direction].join(' ')).addClass('active')
349
445
  $active.removeClass(['active', direction].join(' '))
350
446
  that.sliding = false
351
- setTimeout(function () { that.$element.trigger('slid') }, 0)
447
+ setTimeout(function () {
448
+ that.$element.trigger(slidEvent)
449
+ }, 0)
352
450
  })
353
- .emulateTransitionEnd(600)
451
+ .emulateTransitionEnd(Carousel.TRANSITION_DURATION)
354
452
  } else {
355
- this.$element.trigger(e)
356
- if (e.isDefaultPrevented()) return
357
453
  $active.removeClass('active')
358
454
  $next.addClass('active')
359
455
  this.sliding = false
360
- this.$element.trigger('slid')
456
+ this.$element.trigger(slidEvent)
361
457
  }
362
458
 
363
459
  isCycling && this.cycle()
@@ -369,9 +465,7 @@
369
465
  // CAROUSEL PLUGIN DEFINITION
370
466
  // ==========================
371
467
 
372
- var old = $.fn.carousel
373
-
374
- $.fn.carousel = function (option) {
468
+ function Plugin(option) {
375
469
  return this.each(function () {
376
470
  var $this = $(this)
377
471
  var data = $this.data('bs.carousel')
@@ -385,6 +479,9 @@
385
479
  })
386
480
  }
387
481
 
482
+ var old = $.fn.carousel
483
+
484
+ $.fn.carousel = Plugin
388
485
  $.fn.carousel.Constructor = Carousel
389
486
 
390
487
 
@@ -400,62 +497,272 @@
400
497
  // CAROUSEL DATA-API
401
498
  // =================
402
499
 
403
- $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
404
- var $this = $(this), href
405
- var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
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
406
505
  var options = $.extend({}, $target.data(), $this.data())
407
506
  var slideIndex = $this.attr('data-slide-to')
408
507
  if (slideIndex) options.interval = false
409
508
 
410
- $target.carousel(options)
509
+ Plugin.call($target, options)
411
510
 
412
- if (slideIndex = $this.attr('data-slide-to')) {
511
+ if (slideIndex) {
413
512
  $target.data('bs.carousel').to(slideIndex)
414
513
  }
415
514
 
416
515
  e.preventDefault()
417
- })
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)
418
521
 
419
522
  $(window).on('load', function () {
420
523
  $('[data-ride="carousel"]').each(function () {
421
524
  var $carousel = $(this)
422
- $carousel.carousel($carousel.data())
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]()
423
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)
424
739
  })
425
740
 
426
- }(window.jQuery);
741
+ }(jQuery);
427
742
 
428
743
  /* ========================================================================
429
- * Bootstrap: dropdown.js v3.0.0
430
- * http://twbs.github.com/bootstrap/javascript.html#dropdowns
744
+ * Bootstrap: dropdown.js v3.3.1
745
+ * http://getbootstrap.com/javascript/#dropdowns
431
746
  * ========================================================================
432
- * Copyright 2012 Twitter, Inc.
433
- *
434
- * Licensed under the Apache License, Version 2.0 (the "License");
435
- * you may not use this file except in compliance with the License.
436
- * You may obtain a copy of the License at
437
- *
438
- * http://www.apache.org/licenses/LICENSE-2.0
439
- *
440
- * Unless required by applicable law or agreed to in writing, software
441
- * distributed under the License is distributed on an "AS IS" BASIS,
442
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
443
- * See the License for the specific language governing permissions and
444
- * limitations under the License.
747
+ * Copyright 2011-2014 Twitter, Inc.
748
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
445
749
  * ======================================================================== */
446
750
 
447
751
 
448
- +function ($) { "use strict";
752
+ +function ($) {
753
+ 'use strict';
449
754
 
450
755
  // DROPDOWN CLASS DEFINITION
451
756
  // =========================
452
757
 
453
758
  var backdrop = '.dropdown-backdrop'
454
- var toggle = '[data-toggle=dropdown]'
759
+ var toggle = '[data-toggle="dropdown"]'
455
760
  var Dropdown = function (element) {
456
- var $el = $(element).on('click.bs.dropdown', this.toggle)
761
+ $(element).on('click.bs.dropdown', this.toggle)
457
762
  }
458
763
 
764
+ Dropdown.VERSION = '3.3.1'
765
+
459
766
  Dropdown.prototype.toggle = function (e) {
460
767
  var $this = $(this)
461
768
 
@@ -468,26 +775,29 @@
468
775
 
469
776
  if (!isActive) {
470
777
  if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
471
- // if mobile we we use a backdrop because click events don't delegate
778
+ // if mobile we use a backdrop because click events don't delegate
472
779
  $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
473
780
  }
474
781
 
475
- $parent.trigger(e = $.Event('show.bs.dropdown'))
782
+ var relatedTarget = { relatedTarget: this }
783
+ $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
476
784
 
477
785
  if (e.isDefaultPrevented()) return
478
786
 
787
+ $this
788
+ .trigger('focus')
789
+ .attr('aria-expanded', 'true')
790
+
479
791
  $parent
480
792
  .toggleClass('open')
481
- .trigger('shown.bs.dropdown')
482
-
483
- $this.focus()
793
+ .trigger('shown.bs.dropdown', relatedTarget)
484
794
  }
485
795
 
486
796
  return false
487
797
  }
488
798
 
489
799
  Dropdown.prototype.keydown = function (e) {
490
- if (!/(38|40|27)/.test(e.keyCode)) return
800
+ if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return
491
801
 
492
802
  var $this = $(this)
493
803
 
@@ -499,32 +809,41 @@
499
809
  var $parent = getParent($this)
500
810
  var isActive = $parent.hasClass('open')
501
811
 
502
- if (!isActive || (isActive && e.keyCode == 27)) {
503
- if (e.which == 27) $parent.find(toggle).focus()
504
- return $this.click()
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')
505
815
  }
506
816
 
507
- var $items = $('[role=menu] li:not(.divider):visible a', $parent)
817
+ var desc = ' li:not(.divider):visible a'
818
+ var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
508
819
 
509
820
  if (!$items.length) return
510
821
 
511
- var index = $items.index($items.filter(':focus'))
822
+ var index = $items.index(e.target)
512
823
 
513
- if (e.keyCode == 38 && index > 0) index-- // up
514
- if (e.keyCode == 40 && index < $items.length - 1) index++ // down
515
- if (!~index) index=0
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
516
827
 
517
- $items.eq(index).focus()
828
+ $items.eq(index).trigger('focus')
518
829
  }
519
830
 
520
- function clearMenus() {
831
+ function clearMenus(e) {
832
+ if (e && e.which === 3) return
521
833
  $(backdrop).remove()
522
- $(toggle).each(function (e) {
523
- var $parent = getParent($(this))
834
+ $(toggle).each(function () {
835
+ var $this = $(this)
836
+ var $parent = getParent($this)
837
+ var relatedTarget = { relatedTarget: this }
838
+
524
839
  if (!$parent.hasClass('open')) return
525
- $parent.trigger(e = $.Event('hide.bs.dropdown'))
840
+
841
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
842
+
526
843
  if (e.isDefaultPrevented()) return
527
- $parent.removeClass('open').trigger('hidden.bs.dropdown')
844
+
845
+ $this.attr('aria-expanded', 'false')
846
+ $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
528
847
  })
529
848
  }
530
849
 
@@ -533,7 +852,7 @@
533
852
 
534
853
  if (!selector) {
535
854
  selector = $this.attr('href')
536
- selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
855
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
537
856
  }
538
857
 
539
858
  var $parent = selector && $(selector)
@@ -545,18 +864,19 @@
545
864
  // DROPDOWN PLUGIN DEFINITION
546
865
  // ==========================
547
866
 
548
- var old = $.fn.dropdown
549
-
550
- $.fn.dropdown = function (option) {
867
+ function Plugin(option) {
551
868
  return this.each(function () {
552
869
  var $this = $(this)
553
- var data = $this.data('dropdown')
870
+ var data = $this.data('bs.dropdown')
554
871
 
555
- if (!data) $this.data('dropdown', (data = new Dropdown(this)))
872
+ if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
556
873
  if (typeof option == 'string') data[option].call($this)
557
874
  })
558
875
  }
559
876
 
877
+ var old = $.fn.dropdown
878
+
879
+ $.fn.dropdown = Plugin
560
880
  $.fn.dropdown.Constructor = Dropdown
561
881
 
562
882
 
@@ -575,53 +895,58 @@
575
895
  $(document)
576
896
  .on('click.bs.dropdown.data-api', clearMenus)
577
897
  .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
578
- .on('click.bs.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
579
- .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
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)
580
902
 
581
- }(window.jQuery);
903
+ }(jQuery);
582
904
 
583
905
  /* ========================================================================
584
- * Bootstrap: modal.js v3.0.0
585
- * http://twbs.github.com/bootstrap/javascript.html#modals
906
+ * Bootstrap: modal.js v3.3.1
907
+ * http://getbootstrap.com/javascript/#modals
586
908
  * ========================================================================
587
- * Copyright 2012 Twitter, Inc.
588
- *
589
- * Licensed under the Apache License, Version 2.0 (the "License");
590
- * you may not use this file except in compliance with the License.
591
- * You may obtain a copy of the License at
592
- *
593
- * http://www.apache.org/licenses/LICENSE-2.0
594
- *
595
- * Unless required by applicable law or agreed to in writing, software
596
- * distributed under the License is distributed on an "AS IS" BASIS,
597
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
598
- * See the License for the specific language governing permissions and
599
- * limitations under the License.
909
+ * Copyright 2011-2014 Twitter, Inc.
910
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
600
911
  * ======================================================================== */
601
912
 
602
913
 
603
- +function ($) { "use strict";
914
+ +function ($) {
915
+ 'use strict';
604
916
 
605
917
  // MODAL CLASS DEFINITION
606
918
  // ======================
607
919
 
608
920
  var Modal = function (element, options) {
609
- this.options = options
610
- this.$element = $(element)
611
- this.$backdrop =
612
- this.isShown = null
613
-
614
- if (this.options.remote) this.$element.load(this.options.remote)
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
+ }
615
935
  }
616
936
 
617
- Modal.DEFAULTS = {
618
- backdrop: true
619
- , keyboard: true
620
- , show: true
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
621
946
  }
622
947
 
623
948
  Modal.prototype.toggle = function (_relatedTarget) {
624
- return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
949
+ return this.isShown ? this.hide() : this.show(_relatedTarget)
625
950
  }
626
951
 
627
952
  Modal.prototype.show = function (_relatedTarget) {
@@ -634,18 +959,28 @@
634
959
 
635
960
  this.isShown = true
636
961
 
962
+ this.checkScrollbar()
963
+ this.setScrollbar()
964
+ this.$body.addClass('modal-open')
965
+
637
966
  this.escape()
967
+ this.resize()
638
968
 
639
- this.$element.on('click.dismiss.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
969
+ this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
640
970
 
641
971
  this.backdrop(function () {
642
972
  var transition = $.support.transition && that.$element.hasClass('fade')
643
973
 
644
974
  if (!that.$element.parent().length) {
645
- that.$element.appendTo(document.body) // don't move modals dom position
975
+ that.$element.appendTo(that.$body) // don't move modals dom position
646
976
  }
647
977
 
648
- that.$element.show()
978
+ that.$element
979
+ .show()
980
+ .scrollTop(0)
981
+
982
+ if (that.options.backdrop) that.adjustBackdrop()
983
+ that.adjustDialog()
649
984
 
650
985
  if (transition) {
651
986
  that.$element[0].offsetWidth // force reflow
@@ -661,11 +996,11 @@
661
996
 
662
997
  transition ?
663
998
  that.$element.find('.modal-dialog') // wait for modal to slide in
664
- .one($.support.transition.end, function () {
665
- that.$element.focus().trigger(e)
999
+ .one('bsTransitionEnd', function () {
1000
+ that.$element.trigger('focus').trigger(e)
666
1001
  })
667
- .emulateTransitionEnd(300) :
668
- that.$element.focus().trigger(e)
1002
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
1003
+ that.$element.trigger('focus').trigger(e)
669
1004
  })
670
1005
  }
671
1006
 
@@ -681,18 +1016,19 @@
681
1016
  this.isShown = false
682
1017
 
683
1018
  this.escape()
1019
+ this.resize()
684
1020
 
685
1021
  $(document).off('focusin.bs.modal')
686
1022
 
687
1023
  this.$element
688
1024
  .removeClass('in')
689
1025
  .attr('aria-hidden', true)
690
- .off('click.dismiss.modal')
1026
+ .off('click.dismiss.bs.modal')
691
1027
 
692
1028
  $.support.transition && this.$element.hasClass('fade') ?
693
1029
  this.$element
694
- .one($.support.transition.end, $.proxy(this.hideModal, this))
695
- .emulateTransitionEnd(300) :
1030
+ .one('bsTransitionEnd', $.proxy(this.hideModal, this))
1031
+ .emulateTransitionEnd(Modal.TRANSITION_DURATION) :
696
1032
  this.hideModal()
697
1033
  }
698
1034
 
@@ -701,18 +1037,26 @@
701
1037
  .off('focusin.bs.modal') // guard against infinite focus loop
702
1038
  .on('focusin.bs.modal', $.proxy(function (e) {
703
1039
  if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
704
- this.$element.focus()
1040
+ this.$element.trigger('focus')
705
1041
  }
706
1042
  }, this))
707
1043
  }
708
1044
 
709
1045
  Modal.prototype.escape = function () {
710
1046
  if (this.isShown && this.options.keyboard) {
711
- this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
1047
+ this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) {
712
1048
  e.which == 27 && this.hide()
713
1049
  }, this))
714
1050
  } else if (!this.isShown) {
715
- this.$element.off('keyup.dismiss.bs.modal')
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')
716
1060
  }
717
1061
  }
718
1062
 
@@ -720,7 +1064,9 @@
720
1064
  var that = this
721
1065
  this.$element.hide()
722
1066
  this.backdrop(function () {
723
- that.removeBackdrop()
1067
+ that.$body.removeClass('modal-open')
1068
+ that.resetAdjustments()
1069
+ that.resetScrollbar()
724
1070
  that.$element.trigger('hidden.bs.modal')
725
1071
  })
726
1072
  }
@@ -731,21 +1077,20 @@
731
1077
  }
732
1078
 
733
1079
  Modal.prototype.backdrop = function (callback) {
734
- var that = this
1080
+ var that = this
735
1081
  var animate = this.$element.hasClass('fade') ? 'fade' : ''
736
1082
 
737
1083
  if (this.isShown && this.options.backdrop) {
738
1084
  var doAnimate = $.support.transition && animate
739
1085
 
740
1086
  this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
741
- .appendTo(document.body)
742
-
743
- this.$element.on('click.dismiss.modal', $.proxy(function (e) {
744
- if (e.target !== e.currentTarget) return
745
- this.options.backdrop == 'static'
746
- ? this.$element[0].focus.call(this.$element[0])
747
- : this.hide.call(this)
748
- }, this))
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))
749
1094
 
750
1095
  if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
751
1096
 
@@ -755,31 +1100,85 @@
755
1100
 
756
1101
  doAnimate ?
757
1102
  this.$backdrop
758
- .one($.support.transition.end, callback)
759
- .emulateTransitionEnd(150) :
1103
+ .one('bsTransitionEnd', callback)
1104
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
760
1105
  callback()
761
1106
 
762
1107
  } else if (!this.isShown && this.$backdrop) {
763
1108
  this.$backdrop.removeClass('in')
764
1109
 
765
- $.support.transition && this.$element.hasClass('fade')?
1110
+ var callbackRemove = function () {
1111
+ that.removeBackdrop()
1112
+ callback && callback()
1113
+ }
1114
+ $.support.transition && this.$element.hasClass('fade') ?
766
1115
  this.$backdrop
767
- .one($.support.transition.end, callback)
768
- .emulateTransitionEnd(150) :
769
- callback()
1116
+ .one('bsTransitionEnd', callbackRemove)
1117
+ .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) :
1118
+ callbackRemove()
770
1119
 
771
1120
  } else if (callback) {
772
1121
  callback()
773
1122
  }
774
1123
  }
775
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
+
776
1177
 
777
1178
  // MODAL PLUGIN DEFINITION
778
1179
  // =======================
779
1180
 
780
- var old = $.fn.modal
781
-
782
- $.fn.modal = function (option, _relatedTarget) {
1181
+ function Plugin(option, _relatedTarget) {
783
1182
  return this.each(function () {
784
1183
  var $this = $(this)
785
1184
  var data = $this.data('bs.modal')
@@ -791,6 +1190,9 @@
791
1190
  })
792
1191
  }
793
1192
 
1193
+ var old = $.fn.modal
1194
+
1195
+ $.fn.modal = Plugin
794
1196
  $.fn.modal.Constructor = Modal
795
1197
 
796
1198
 
@@ -809,46 +1211,34 @@
809
1211
  $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
810
1212
  var $this = $(this)
811
1213
  var href = $this.attr('href')
812
- var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
813
- var option = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
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())
814
1216
 
815
- e.preventDefault()
1217
+ if ($this.is('a')) e.preventDefault()
816
1218
 
817
- $target
818
- .modal(option, this)
819
- .one('hide', function () {
820
- $this.is(':visible') && $this.focus()
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')
821
1223
  })
1224
+ })
1225
+ Plugin.call($target, option, this)
822
1226
  })
823
1227
 
824
- $(document)
825
- .on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
826
- .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
827
-
828
- }(window.jQuery);
1228
+ }(jQuery);
829
1229
 
830
1230
  /* ========================================================================
831
- * Bootstrap: tooltip.js v3.0.0
832
- * http://twbs.github.com/bootstrap/javascript.html#tooltip
1231
+ * Bootstrap: tooltip.js v3.3.1
1232
+ * http://getbootstrap.com/javascript/#tooltip
833
1233
  * Inspired by the original jQuery.tipsy by Jason Frame
834
1234
  * ========================================================================
835
- * Copyright 2012 Twitter, Inc.
836
- *
837
- * Licensed under the Apache License, Version 2.0 (the "License");
838
- * you may not use this file except in compliance with the License.
839
- * You may obtain a copy of the License at
840
- *
841
- * http://www.apache.org/licenses/LICENSE-2.0
842
- *
843
- * Unless required by applicable law or agreed to in writing, software
844
- * distributed under the License is distributed on an "AS IS" BASIS,
845
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
846
- * See the License for the specific language governing permissions and
847
- * limitations under the License.
1235
+ * Copyright 2011-2014 Twitter, Inc.
1236
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
848
1237
  * ======================================================================== */
849
1238
 
850
1239
 
851
- +function ($) { "use strict";
1240
+ +function ($) {
1241
+ 'use strict';
852
1242
 
853
1243
  // TOOLTIP PUBLIC CLASS DEFINITION
854
1244
  // ===============================
@@ -864,23 +1254,32 @@
864
1254
  this.init('tooltip', element, options)
865
1255
  }
866
1256
 
1257
+ Tooltip.VERSION = '3.3.1'
1258
+
1259
+ Tooltip.TRANSITION_DURATION = 150
1260
+
867
1261
  Tooltip.DEFAULTS = {
868
- animation: true
869
- , placement: 'top'
870
- , selector: false
871
- , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
872
- , trigger: 'hover focus'
873
- , title: ''
874
- , delay: 0
875
- , html: false
876
- , container: false
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
+ }
877
1275
  }
878
1276
 
879
1277
  Tooltip.prototype.init = function (type, element, options) {
880
- this.enabled = true
881
- this.type = type
882
- this.$element = $(element)
883
- this.options = this.getOptions(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)
884
1283
 
885
1284
  var triggers = this.options.trigger.split(' ')
886
1285
 
@@ -890,8 +1289,8 @@
890
1289
  if (trigger == 'click') {
891
1290
  this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
892
1291
  } else if (trigger != 'manual') {
893
- var eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
894
- var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
1292
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
1293
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
895
1294
 
896
1295
  this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
897
1296
  this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
@@ -912,8 +1311,8 @@
912
1311
 
913
1312
  if (options.delay && typeof options.delay == 'number') {
914
1313
  options.delay = {
915
- show: options.delay
916
- , hide: options.delay
1314
+ show: options.delay,
1315
+ hide: options.delay
917
1316
  }
918
1317
  }
919
1318
 
@@ -933,7 +1332,17 @@
933
1332
 
934
1333
  Tooltip.prototype.enter = function (obj) {
935
1334
  var self = obj instanceof this.constructor ?
936
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
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
+ }
937
1346
 
938
1347
  clearTimeout(self.timeout)
939
1348
 
@@ -948,7 +1357,12 @@
948
1357
 
949
1358
  Tooltip.prototype.leave = function (obj) {
950
1359
  var self = obj instanceof this.constructor ?
951
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
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
+ }
952
1366
 
953
1367
  clearTimeout(self.timeout)
954
1368
 
@@ -962,16 +1376,22 @@
962
1376
  }
963
1377
 
964
1378
  Tooltip.prototype.show = function () {
965
- var e = $.Event('show.bs.'+ this.type)
1379
+ var e = $.Event('show.bs.' + this.type)
966
1380
 
967
1381
  if (this.hasContent() && this.enabled) {
968
1382
  this.$element.trigger(e)
969
1383
 
970
- if (e.isDefaultPrevented()) return
1384
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
1385
+ if (e.isDefaultPrevented() || !inDom) return
1386
+ var that = this
971
1387
 
972
1388
  var $tip = this.tip()
973
1389
 
1390
+ var tipId = this.getUID(this.type)
1391
+
974
1392
  this.setContent()
1393
+ $tip.attr('id', tipId)
1394
+ this.$element.attr('aria-describedby', tipId)
975
1395
 
976
1396
  if (this.options.animation) $tip.addClass('fade')
977
1397
 
@@ -987,6 +1407,7 @@
987
1407
  .detach()
988
1408
  .css({ top: 0, left: 0, display: 'block' })
989
1409
  .addClass(placement)
1410
+ .data('bs.' + this.type, this)
990
1411
 
991
1412
  this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
992
1413
 
@@ -995,18 +1416,14 @@
995
1416
  var actualHeight = $tip[0].offsetHeight
996
1417
 
997
1418
  if (autoPlace) {
998
- var $parent = this.$element.parent()
999
-
1000
1419
  var orgPlacement = placement
1001
- var docScroll = document.documentElement.scrollTop || document.body.scrollTop
1002
- var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
1003
- var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
1004
- var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
1005
-
1006
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
1007
- placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
1008
- placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
1009
- placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
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' :
1010
1427
  placement
1011
1428
 
1012
1429
  $tip
@@ -1017,12 +1434,24 @@
1017
1434
  var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
1018
1435
 
1019
1436
  this.applyPlacement(calculatedOffset, placement)
1020
- this.$element.trigger('shown.bs.' + this.type)
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()
1021
1451
  }
1022
1452
  }
1023
1453
 
1024
- Tooltip.prototype.applyPlacement = function(offset, placement) {
1025
- var replace
1454
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
1026
1455
  var $tip = this.tip()
1027
1456
  var width = $tip[0].offsetWidth
1028
1457
  var height = $tip[0].offsetHeight
@@ -1038,42 +1467,44 @@
1038
1467
  offset.top = offset.top + marginTop
1039
1468
  offset.left = offset.left + marginLeft
1040
1469
 
1041
- $tip
1042
- .offset(offset)
1043
- .addClass('in')
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')
1044
1482
 
1045
1483
  // check to see if placing tip in new offset caused the tip to resize itself
1046
1484
  var actualWidth = $tip[0].offsetWidth
1047
1485
  var actualHeight = $tip[0].offsetHeight
1048
1486
 
1049
1487
  if (placement == 'top' && actualHeight != height) {
1050
- replace = true
1051
1488
  offset.top = offset.top + height - actualHeight
1052
1489
  }
1053
1490
 
1054
- if (/bottom|top/.test(placement)) {
1055
- var delta = 0
1056
-
1057
- if (offset.left < 0) {
1058
- delta = offset.left * -2
1059
- offset.left = 0
1491
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
1060
1492
 
1061
- $tip.offset(offset)
1062
-
1063
- actualWidth = $tip[0].offsetWidth
1064
- actualHeight = $tip[0].offsetHeight
1065
- }
1493
+ if (delta.left) offset.left += delta.left
1494
+ else offset.top += delta.top
1066
1495
 
1067
- this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
1068
- } else {
1069
- this.replaceArrow(actualHeight - height, actualHeight, 'top')
1070
- }
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'
1071
1499
 
1072
- if (replace) $tip.offset(offset)
1500
+ $tip.offset(offset)
1501
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
1073
1502
  }
1074
1503
 
1075
- Tooltip.prototype.replaceArrow = function(delta, dimension, position) {
1076
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
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', '')
1077
1508
  }
1078
1509
 
1079
1510
  Tooltip.prototype.setContent = function () {
@@ -1084,13 +1515,17 @@
1084
1515
  $tip.removeClass('fade in top bottom left right')
1085
1516
  }
1086
1517
 
1087
- Tooltip.prototype.hide = function () {
1518
+ Tooltip.prototype.hide = function (callback) {
1088
1519
  var that = this
1089
1520
  var $tip = this.tip()
1090
1521
  var e = $.Event('hide.bs.' + this.type)
1091
1522
 
1092
1523
  function complete() {
1093
1524
  if (that.hoverState != 'in') $tip.detach()
1525
+ that.$element
1526
+ .removeAttr('aria-describedby')
1527
+ .trigger('hidden.bs.' + that.type)
1528
+ callback && callback()
1094
1529
  }
1095
1530
 
1096
1531
  this.$element.trigger(e)
@@ -1101,18 +1536,18 @@
1101
1536
 
1102
1537
  $.support.transition && this.$tip.hasClass('fade') ?
1103
1538
  $tip
1104
- .one($.support.transition.end, complete)
1105
- .emulateTransitionEnd(150) :
1539
+ .one('bsTransitionEnd', complete)
1540
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
1106
1541
  complete()
1107
1542
 
1108
- this.$element.trigger('hidden.bs.' + this.type)
1543
+ this.hoverState = null
1109
1544
 
1110
1545
  return this
1111
1546
  }
1112
1547
 
1113
1548
  Tooltip.prototype.fixTitle = function () {
1114
1549
  var $e = this.$element
1115
- if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
1550
+ if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
1116
1551
  $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
1117
1552
  }
1118
1553
  }
@@ -1121,12 +1556,22 @@
1121
1556
  return this.getTitle()
1122
1557
  }
1123
1558
 
1124
- Tooltip.prototype.getPosition = function () {
1125
- var el = this.$element[0]
1126
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
1127
- width: el.offsetWidth
1128
- , height: el.offsetHeight
1129
- }, this.$element.offset())
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)
1130
1575
  }
1131
1576
 
1132
1577
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
@@ -1134,6 +1579,35 @@
1134
1579
  placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
1135
1580
  placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
1136
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
1137
1611
  }
1138
1612
 
1139
1613
  Tooltip.prototype.getTitle = function () {
@@ -1147,20 +1621,18 @@
1147
1621
  return title
1148
1622
  }
1149
1623
 
1150
- Tooltip.prototype.tip = function () {
1151
- return this.$tip = this.$tip || $(this.options.template)
1624
+ Tooltip.prototype.getUID = function (prefix) {
1625
+ do prefix += ~~(Math.random() * 1000000)
1626
+ while (document.getElementById(prefix))
1627
+ return prefix
1152
1628
  }
1153
1629
 
1154
- Tooltip.prototype.arrow = function () {
1155
- return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
1630
+ Tooltip.prototype.tip = function () {
1631
+ return (this.$tip = this.$tip || $(this.options.template))
1156
1632
  }
1157
1633
 
1158
- Tooltip.prototype.validate = function () {
1159
- if (!this.$element[0].parentNode) {
1160
- this.hide()
1161
- this.$element = null
1162
- this.options = null
1163
- }
1634
+ Tooltip.prototype.arrow = function () {
1635
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
1164
1636
  }
1165
1637
 
1166
1638
  Tooltip.prototype.enable = function () {
@@ -1176,31 +1648,51 @@
1176
1648
  }
1177
1649
 
1178
1650
  Tooltip.prototype.toggle = function (e) {
1179
- var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
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
+
1180
1660
  self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
1181
1661
  }
1182
1662
 
1183
1663
  Tooltip.prototype.destroy = function () {
1184
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
1664
+ var that = this
1665
+ clearTimeout(this.timeout)
1666
+ this.hide(function () {
1667
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
1668
+ })
1185
1669
  }
1186
1670
 
1187
1671
 
1188
1672
  // TOOLTIP PLUGIN DEFINITION
1189
1673
  // =========================
1190
1674
 
1191
- var old = $.fn.tooltip
1192
-
1193
- $.fn.tooltip = function (option) {
1675
+ function Plugin(option) {
1194
1676
  return this.each(function () {
1195
- var $this = $(this)
1196
- var data = $this.data('bs.tooltip')
1197
- var options = typeof option == 'object' && option
1198
-
1199
- if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
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
+ }
1200
1689
  if (typeof option == 'string') data[option]()
1201
1690
  })
1202
1691
  }
1203
1692
 
1693
+ var old = $.fn.tooltip
1694
+
1695
+ $.fn.tooltip = Plugin
1204
1696
  $.fn.tooltip.Constructor = Tooltip
1205
1697
 
1206
1698
 
@@ -1212,29 +1704,19 @@
1212
1704
  return this
1213
1705
  }
1214
1706
 
1215
- }(window.jQuery);
1707
+ }(jQuery);
1216
1708
 
1217
1709
  /* ========================================================================
1218
- * Bootstrap: popover.js v3.0.0
1219
- * http://twbs.github.com/bootstrap/javascript.html#popovers
1710
+ * Bootstrap: popover.js v3.3.1
1711
+ * http://getbootstrap.com/javascript/#popovers
1220
1712
  * ========================================================================
1221
- * Copyright 2012 Twitter, Inc.
1222
- *
1223
- * Licensed under the Apache License, Version 2.0 (the "License");
1224
- * you may not use this file except in compliance with the License.
1225
- * You may obtain a copy of the License at
1226
- *
1227
- * http://www.apache.org/licenses/LICENSE-2.0
1228
- *
1229
- * Unless required by applicable law or agreed to in writing, software
1230
- * distributed under the License is distributed on an "AS IS" BASIS,
1231
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1232
- * See the License for the specific language governing permissions and
1233
- * limitations under the License.
1713
+ * Copyright 2011-2014 Twitter, Inc.
1714
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1234
1715
  * ======================================================================== */
1235
1716
 
1236
1717
 
1237
- +function ($) { "use strict";
1718
+ +function ($) {
1719
+ 'use strict';
1238
1720
 
1239
1721
  // POPOVER PUBLIC CLASS DEFINITION
1240
1722
  // ===============================
@@ -1245,11 +1727,13 @@
1245
1727
 
1246
1728
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
1247
1729
 
1248
- Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {
1249
- placement: 'right'
1250
- , trigger: 'click'
1251
- , content: ''
1252
- , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
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>'
1253
1737
  })
1254
1738
 
1255
1739
 
@@ -1270,7 +1754,9 @@
1270
1754
  var content = this.getContent()
1271
1755
 
1272
1756
  $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
1273
- $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)
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)
1274
1760
 
1275
1761
  $tip.removeClass('fade top bottom left right in')
1276
1762
 
@@ -1294,7 +1780,7 @@
1294
1780
  }
1295
1781
 
1296
1782
  Popover.prototype.arrow = function () {
1297
- return this.$arrow = this.$arrow || this.tip().find('.arrow')
1783
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
1298
1784
  }
1299
1785
 
1300
1786
  Popover.prototype.tip = function () {
@@ -1306,19 +1792,27 @@
1306
1792
  // POPOVER PLUGIN DEFINITION
1307
1793
  // =========================
1308
1794
 
1309
- var old = $.fn.popover
1310
-
1311
- $.fn.popover = function (option) {
1795
+ function Plugin(option) {
1312
1796
  return this.each(function () {
1313
- var $this = $(this)
1314
- var data = $this.data('bs.popover')
1315
- var options = typeof option == 'object' && option
1316
-
1317
- if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
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
+ }
1318
1809
  if (typeof option == 'string') data[option]()
1319
1810
  })
1320
1811
  }
1321
1812
 
1813
+ var old = $.fn.popover
1814
+
1815
+ $.fn.popover = Plugin
1322
1816
  $.fn.popover.Constructor = Popover
1323
1817
 
1324
1818
 
@@ -1330,29 +1824,195 @@
1330
1824
  return this
1331
1825
  }
1332
1826
 
1333
- }(window.jQuery);
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);
1334
2004
 
1335
2005
  /* ========================================================================
1336
- * Bootstrap: tab.js v3.0.0
1337
- * http://twbs.github.com/bootstrap/javascript.html#tabs
2006
+ * Bootstrap: tab.js v3.3.1
2007
+ * http://getbootstrap.com/javascript/#tabs
1338
2008
  * ========================================================================
1339
- * Copyright 2012 Twitter, Inc.
1340
- *
1341
- * Licensed under the Apache License, Version 2.0 (the "License");
1342
- * you may not use this file except in compliance with the License.
1343
- * You may obtain a copy of the License at
1344
- *
1345
- * http://www.apache.org/licenses/LICENSE-2.0
1346
- *
1347
- * Unless required by applicable law or agreed to in writing, software
1348
- * distributed under the License is distributed on an "AS IS" BASIS,
1349
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1350
- * See the License for the specific language governing permissions and
1351
- * limitations under the License.
2009
+ * Copyright 2011-2014 Twitter, Inc.
2010
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1352
2011
  * ======================================================================== */
1353
2012
 
1354
2013
 
1355
- +function ($) { "use strict";
2014
+ +function ($) {
2015
+ 'use strict';
1356
2016
 
1357
2017
  // TAB CLASS DEFINITION
1358
2018
  // ====================
@@ -1361,34 +2021,46 @@
1361
2021
  this.element = $(element)
1362
2022
  }
1363
2023
 
2024
+ Tab.VERSION = '3.3.1'
2025
+
2026
+ Tab.TRANSITION_DURATION = 150
2027
+
1364
2028
  Tab.prototype.show = function () {
1365
2029
  var $this = this.element
1366
2030
  var $ul = $this.closest('ul:not(.dropdown-menu)')
1367
- var selector = $this.attr('data-target')
2031
+ var selector = $this.data('target')
1368
2032
 
1369
2033
  if (!selector) {
1370
2034
  selector = $this.attr('href')
1371
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
2035
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
1372
2036
  }
1373
2037
 
1374
2038
  if ($this.parent('li').hasClass('active')) return
1375
2039
 
1376
- var previous = $ul.find('.active:last a')[0]
1377
- var e = $.Event('show.bs.tab', {
1378
- relatedTarget: previous
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]
1379
2046
  })
1380
2047
 
1381
- $this.trigger(e)
2048
+ $previous.trigger(hideEvent)
2049
+ $this.trigger(showEvent)
1382
2050
 
1383
- if (e.isDefaultPrevented()) return
2051
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
1384
2052
 
1385
2053
  var $target = $(selector)
1386
2054
 
1387
- this.activate($this.parent('li'), $ul)
2055
+ this.activate($this.closest('li'), $ul)
1388
2056
  this.activate($target, $target.parent(), function () {
2057
+ $previous.trigger({
2058
+ type: 'hidden.bs.tab',
2059
+ relatedTarget: $this[0]
2060
+ })
1389
2061
  $this.trigger({
1390
- type: 'shown.bs.tab'
1391
- , relatedTarget: previous
2062
+ type: 'shown.bs.tab',
2063
+ relatedTarget: $previous[0]
1392
2064
  })
1393
2065
  })
1394
2066
  }
@@ -1397,15 +2069,21 @@
1397
2069
  var $active = container.find('> .active')
1398
2070
  var transition = callback
1399
2071
  && $.support.transition
1400
- && $active.hasClass('fade')
2072
+ && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
1401
2073
 
1402
2074
  function next() {
1403
2075
  $active
1404
2076
  .removeClass('active')
1405
2077
  .find('> .dropdown-menu > .active')
1406
- .removeClass('active')
2078
+ .removeClass('active')
2079
+ .end()
2080
+ .find('[data-toggle="tab"]')
2081
+ .attr('aria-expanded', false)
1407
2082
 
1408
- element.addClass('active')
2083
+ element
2084
+ .addClass('active')
2085
+ .find('[data-toggle="tab"]')
2086
+ .attr('aria-expanded', true)
1409
2087
 
1410
2088
  if (transition) {
1411
2089
  element[0].offsetWidth // reflow for transition
@@ -1415,16 +2093,21 @@
1415
2093
  }
1416
2094
 
1417
2095
  if (element.parent('.dropdown-menu')) {
1418
- element.closest('li.dropdown').addClass('active')
2096
+ element
2097
+ .closest('li.dropdown')
2098
+ .addClass('active')
2099
+ .end()
2100
+ .find('[data-toggle="tab"]')
2101
+ .attr('aria-expanded', true)
1419
2102
  }
1420
2103
 
1421
2104
  callback && callback()
1422
2105
  }
1423
2106
 
1424
- transition ?
2107
+ $active.length && transition ?
1425
2108
  $active
1426
- .one($.support.transition.end, next)
1427
- .emulateTransitionEnd(150) :
2109
+ .one('bsTransitionEnd', next)
2110
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
1428
2111
  next()
1429
2112
 
1430
2113
  $active.removeClass('in')
@@ -1434,9 +2117,7 @@
1434
2117
  // TAB PLUGIN DEFINITION
1435
2118
  // =====================
1436
2119
 
1437
- var old = $.fn.tab
1438
-
1439
- $.fn.tab = function ( option ) {
2120
+ function Plugin(option) {
1440
2121
  return this.each(function () {
1441
2122
  var $this = $(this)
1442
2123
  var data = $this.data('bs.tab')
@@ -1446,6 +2127,9 @@
1446
2127
  })
1447
2128
  }
1448
2129
 
2130
+ var old = $.fn.tab
2131
+
2132
+ $.fn.tab = Plugin
1449
2133
  $.fn.tab.Constructor = Tab
1450
2134
 
1451
2135
 
@@ -1461,55 +2145,84 @@
1461
2145
  // TAB DATA-API
1462
2146
  // ============
1463
2147
 
1464
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
2148
+ var clickHandler = function (e) {
1465
2149
  e.preventDefault()
1466
- $(this).tab('show')
1467
- })
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)
1468
2156
 
1469
- }(window.jQuery);
2157
+ }(jQuery);
1470
2158
 
1471
2159
  /* ========================================================================
1472
- * Bootstrap: affix.js v3.0.0
1473
- * http://twbs.github.com/bootstrap/javascript.html#affix
2160
+ * Bootstrap: affix.js v3.3.1
2161
+ * http://getbootstrap.com/javascript/#affix
1474
2162
  * ========================================================================
1475
- * Copyright 2012 Twitter, Inc.
1476
- *
1477
- * Licensed under the Apache License, Version 2.0 (the "License");
1478
- * you may not use this file except in compliance with the License.
1479
- * You may obtain a copy of the License at
1480
- *
1481
- * http://www.apache.org/licenses/LICENSE-2.0
1482
- *
1483
- * Unless required by applicable law or agreed to in writing, software
1484
- * distributed under the License is distributed on an "AS IS" BASIS,
1485
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1486
- * See the License for the specific language governing permissions and
1487
- * limitations under the License.
2163
+ * Copyright 2011-2014 Twitter, Inc.
2164
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
1488
2165
  * ======================================================================== */
1489
2166
 
1490
2167
 
1491
- +function ($) { "use strict";
2168
+ +function ($) {
2169
+ 'use strict';
1492
2170
 
1493
2171
  // AFFIX CLASS DEFINITION
1494
2172
  // ======================
1495
2173
 
1496
2174
  var Affix = function (element, options) {
1497
2175
  this.options = $.extend({}, Affix.DEFAULTS, options)
1498
- this.$window = $(window)
2176
+
2177
+ this.$target = $(this.options.target)
1499
2178
  .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
1500
2179
  .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this))
1501
2180
 
1502
- this.$element = $(element)
1503
- this.affixed =
1504
- this.unpin = null
2181
+ this.$element = $(element)
2182
+ this.affixed =
2183
+ this.unpin =
2184
+ this.pinnedOffset = null
1505
2185
 
1506
2186
  this.checkPosition()
1507
2187
  }
1508
2188
 
1509
- Affix.RESET = 'affix affix-top affix-bottom'
2189
+ Affix.VERSION = '3.3.1'
2190
+
2191
+ Affix.RESET = 'affix affix-top affix-bottom'
1510
2192
 
1511
2193
  Affix.DEFAULTS = {
1512
- offset: 0
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)
1513
2226
  }
1514
2227
 
1515
2228
  Affix.prototype.checkPositionWithEventLoop = function () {
@@ -1519,31 +2232,41 @@
1519
2232
  Affix.prototype.checkPosition = function () {
1520
2233
  if (!this.$element.is(':visible')) return
1521
2234
 
1522
- var scrollHeight = $(document).height()
1523
- var scrollTop = this.$window.scrollTop()
1524
- var position = this.$element.offset()
2235
+ var height = this.$element.height()
1525
2236
  var offset = this.options.offset
1526
2237
  var offsetTop = offset.top
1527
2238
  var offsetBottom = offset.bottom
2239
+ var scrollHeight = $('body').height()
1528
2240
 
1529
2241
  if (typeof offset != 'object') offsetBottom = offsetTop = offset
1530
- if (typeof offsetTop == 'function') offsetTop = offset.top()
1531
- if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()
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', '')
1532
2249
 
1533
- var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false :
1534
- offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
1535
- offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false
2250
+ var affixType = 'affix' + (affix ? '-' + affix : '')
2251
+ var e = $.Event(affixType + '.bs.affix')
1536
2252
 
1537
- if (this.affixed === affix) return
1538
- if (this.unpin) this.$element.css('top', '')
2253
+ this.$element.trigger(e)
2254
+
2255
+ if (e.isDefaultPrevented()) return
1539
2256
 
1540
- this.affixed = affix
1541
- this.unpin = affix == 'bottom' ? position.top - scrollTop : null
2257
+ this.affixed = affix
2258
+ this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
1542
2259
 
1543
- this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))
2260
+ this.$element
2261
+ .removeClass(Affix.RESET)
2262
+ .addClass(affixType)
2263
+ .trigger(affixType.replace('affix', 'affixed') + '.bs.affix')
2264
+ }
1544
2265
 
1545
2266
  if (affix == 'bottom') {
1546
- this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })
2267
+ this.$element.offset({
2268
+ top: scrollHeight - height - offsetBottom
2269
+ })
1547
2270
  }
1548
2271
  }
1549
2272
 
@@ -1551,9 +2274,7 @@
1551
2274
  // AFFIX PLUGIN DEFINITION
1552
2275
  // =======================
1553
2276
 
1554
- var old = $.fn.affix
1555
-
1556
- $.fn.affix = function (option) {
2277
+ function Plugin(option) {
1557
2278
  return this.each(function () {
1558
2279
  var $this = $(this)
1559
2280
  var data = $this.data('bs.affix')
@@ -1564,6 +2285,9 @@
1564
2285
  })
1565
2286
  }
1566
2287
 
2288
+ var old = $.fn.affix
2289
+
2290
+ $.fn.affix = Plugin
1567
2291
  $.fn.affix.Constructor = Affix
1568
2292
 
1569
2293
 
@@ -1586,407 +2310,11 @@
1586
2310
 
1587
2311
  data.offset = data.offset || {}
1588
2312
 
1589
- if (data.offsetBottom) data.offset.bottom = data.offsetBottom
1590
- if (data.offsetTop) data.offset.top = data.offsetTop
1591
-
1592
- $spy.affix(data)
1593
- })
1594
- })
1595
-
1596
- }(window.jQuery);
1597
-
1598
- /* ========================================================================
1599
- * Bootstrap: collapse.js v3.0.0
1600
- * http://twbs.github.com/bootstrap/javascript.html#collapse
1601
- * ========================================================================
1602
- * Copyright 2012 Twitter, Inc.
1603
- *
1604
- * Licensed under the Apache License, Version 2.0 (the "License");
1605
- * you may not use this file except in compliance with the License.
1606
- * You may obtain a copy of the License at
1607
- *
1608
- * http://www.apache.org/licenses/LICENSE-2.0
1609
- *
1610
- * Unless required by applicable law or agreed to in writing, software
1611
- * distributed under the License is distributed on an "AS IS" BASIS,
1612
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1613
- * See the License for the specific language governing permissions and
1614
- * limitations under the License.
1615
- * ======================================================================== */
1616
-
1617
-
1618
- +function ($) { "use strict";
1619
-
1620
- // COLLAPSE PUBLIC CLASS DEFINITION
1621
- // ================================
1622
-
1623
- var Collapse = function (element, options) {
1624
- this.$element = $(element)
1625
- this.options = $.extend({}, Collapse.DEFAULTS, options)
1626
- this.transitioning = null
1627
-
1628
- if (this.options.parent) this.$parent = $(this.options.parent)
1629
- if (this.options.toggle) this.toggle()
1630
- }
1631
-
1632
- Collapse.DEFAULTS = {
1633
- toggle: true
1634
- }
1635
-
1636
- Collapse.prototype.dimension = function () {
1637
- var hasWidth = this.$element.hasClass('width')
1638
- return hasWidth ? 'width' : 'height'
1639
- }
1640
-
1641
- Collapse.prototype.show = function () {
1642
- if (this.transitioning || this.$element.hasClass('in')) return
1643
-
1644
- var startEvent = $.Event('show.bs.collapse')
1645
- this.$element.trigger(startEvent)
1646
- if (startEvent.isDefaultPrevented()) return
1647
-
1648
- var actives = this.$parent && this.$parent.find('> .panel > .in')
1649
-
1650
- if (actives && actives.length) {
1651
- var hasData = actives.data('bs.collapse')
1652
- if (hasData && hasData.transitioning) return
1653
- actives.collapse('hide')
1654
- hasData || actives.data('bs.collapse', null)
1655
- }
1656
-
1657
- var dimension = this.dimension()
1658
-
1659
- this.$element
1660
- .removeClass('collapse')
1661
- .addClass('collapsing')
1662
- [dimension](0)
1663
-
1664
- this.transitioning = 1
1665
-
1666
- var complete = function () {
1667
- this.$element
1668
- .removeClass('collapsing')
1669
- .addClass('in')
1670
- [dimension]('auto')
1671
- this.transitioning = 0
1672
- this.$element.trigger('shown.bs.collapse')
1673
- }
1674
-
1675
- if (!$.support.transition) return complete.call(this)
1676
-
1677
- var scrollSize = $.camelCase(['scroll', dimension].join('-'))
1678
-
1679
- this.$element
1680
- .one($.support.transition.end, $.proxy(complete, this))
1681
- .emulateTransitionEnd(350)
1682
- [dimension](this.$element[0][scrollSize])
1683
- }
1684
-
1685
- Collapse.prototype.hide = function () {
1686
- if (this.transitioning || !this.$element.hasClass('in')) return
1687
-
1688
- var startEvent = $.Event('hide.bs.collapse')
1689
- this.$element.trigger(startEvent)
1690
- if (startEvent.isDefaultPrevented()) return
1691
-
1692
- var dimension = this.dimension()
1693
-
1694
- this.$element
1695
- [dimension](this.$element[dimension]())
1696
- [0].offsetHeight
1697
-
1698
- this.$element
1699
- .addClass('collapsing')
1700
- .removeClass('collapse')
1701
- .removeClass('in')
1702
-
1703
- this.transitioning = 1
1704
-
1705
- var complete = function () {
1706
- this.transitioning = 0
1707
- this.$element
1708
- .trigger('hidden.bs.collapse')
1709
- .removeClass('collapsing')
1710
- .addClass('collapse')
1711
- }
1712
-
1713
- if (!$.support.transition) return complete.call(this)
1714
-
1715
- this.$element
1716
- [dimension](0)
1717
- .one($.support.transition.end, $.proxy(complete, this))
1718
- .emulateTransitionEnd(350)
1719
- }
1720
-
1721
- Collapse.prototype.toggle = function () {
1722
- this[this.$element.hasClass('in') ? 'hide' : 'show']()
1723
- }
1724
-
1725
-
1726
- // COLLAPSE PLUGIN DEFINITION
1727
- // ==========================
1728
-
1729
- var old = $.fn.collapse
1730
-
1731
- $.fn.collapse = function (option) {
1732
- return this.each(function () {
1733
- var $this = $(this)
1734
- var data = $this.data('bs.collapse')
1735
- var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
1736
-
1737
- if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
1738
- if (typeof option == 'string') data[option]()
1739
- })
1740
- }
1741
-
1742
- $.fn.collapse.Constructor = Collapse
1743
-
1744
-
1745
- // COLLAPSE NO CONFLICT
1746
- // ====================
1747
-
1748
- $.fn.collapse.noConflict = function () {
1749
- $.fn.collapse = old
1750
- return this
1751
- }
1752
-
2313
+ if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom
2314
+ if (data.offsetTop != null) data.offset.top = data.offsetTop
1753
2315
 
1754
- // COLLAPSE DATA-API
1755
- // =================
1756
-
1757
- $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {
1758
- var $this = $(this), href
1759
- var target = $this.attr('data-target')
1760
- || e.preventDefault()
1761
- || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7
1762
- var $target = $(target)
1763
- var data = $target.data('bs.collapse')
1764
- var option = data ? 'toggle' : $this.data()
1765
- var parent = $this.attr('data-parent')
1766
- var $parent = parent && $(parent)
1767
-
1768
- if (!data || !data.transitioning) {
1769
- if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed')
1770
- $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
1771
- }
1772
-
1773
- $target.collapse(option)
1774
- })
1775
-
1776
- }(window.jQuery);
1777
-
1778
- /* ========================================================================
1779
- * Bootstrap: scrollspy.js v3.0.0
1780
- * http://twbs.github.com/bootstrap/javascript.html#scrollspy
1781
- * ========================================================================
1782
- * Copyright 2012 Twitter, Inc.
1783
- *
1784
- * Licensed under the Apache License, Version 2.0 (the "License");
1785
- * you may not use this file except in compliance with the License.
1786
- * You may obtain a copy of the License at
1787
- *
1788
- * http://www.apache.org/licenses/LICENSE-2.0
1789
- *
1790
- * Unless required by applicable law or agreed to in writing, software
1791
- * distributed under the License is distributed on an "AS IS" BASIS,
1792
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1793
- * See the License for the specific language governing permissions and
1794
- * limitations under the License.
1795
- * ======================================================================== */
1796
-
1797
-
1798
- +function ($) { "use strict";
1799
-
1800
- // SCROLLSPY CLASS DEFINITION
1801
- // ==========================
1802
-
1803
- function ScrollSpy(element, options) {
1804
- var href
1805
- var process = $.proxy(this.process, this)
1806
-
1807
- this.$element = $(element).is('body') ? $(window) : $(element)
1808
- this.$body = $('body')
1809
- this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)
1810
- this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
1811
- this.selector = (this.options.target
1812
- || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
1813
- || '') + ' .nav li > a'
1814
- this.offsets = $([])
1815
- this.targets = $([])
1816
- this.activeTarget = null
1817
-
1818
- this.refresh()
1819
- this.process()
1820
- }
1821
-
1822
- ScrollSpy.DEFAULTS = {
1823
- offset: 10
1824
- }
1825
-
1826
- ScrollSpy.prototype.refresh = function () {
1827
- var offsetMethod = this.$element[0] == window ? 'offset' : 'position'
1828
-
1829
- this.offsets = $([])
1830
- this.targets = $([])
1831
-
1832
- var self = this
1833
- var $targets = this.$body
1834
- .find(this.selector)
1835
- .map(function () {
1836
- var $el = $(this)
1837
- var href = $el.data('target') || $el.attr('href')
1838
- var $href = /^#\w/.test(href) && $(href)
1839
-
1840
- return ($href
1841
- && $href.length
1842
- && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
1843
- })
1844
- .sort(function (a, b) { return a[0] - b[0] })
1845
- .each(function () {
1846
- self.offsets.push(this[0])
1847
- self.targets.push(this[1])
1848
- })
1849
- }
1850
-
1851
- ScrollSpy.prototype.process = function () {
1852
- var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
1853
- var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight
1854
- var maxScroll = scrollHeight - this.$scrollElement.height()
1855
- var offsets = this.offsets
1856
- var targets = this.targets
1857
- var activeTarget = this.activeTarget
1858
- var i
1859
-
1860
- if (scrollTop >= maxScroll) {
1861
- return activeTarget != (i = targets.last()[0]) && this.activate(i)
1862
- }
1863
-
1864
- for (i = offsets.length; i--;) {
1865
- activeTarget != targets[i]
1866
- && scrollTop >= offsets[i]
1867
- && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
1868
- && this.activate( targets[i] )
1869
- }
1870
- }
1871
-
1872
- ScrollSpy.prototype.activate = function (target) {
1873
- this.activeTarget = target
1874
-
1875
- $(this.selector)
1876
- .parents('.active')
1877
- .removeClass('active')
1878
-
1879
- var selector = this.selector
1880
- + '[data-target="' + target + '"],'
1881
- + this.selector + '[href="' + target + '"]'
1882
-
1883
- var active = $(selector)
1884
- .parents('li')
1885
- .addClass('active')
1886
-
1887
- if (active.parent('.dropdown-menu').length) {
1888
- active = active
1889
- .closest('li.dropdown')
1890
- .addClass('active')
1891
- }
1892
-
1893
- active.trigger('activate')
1894
- }
1895
-
1896
-
1897
- // SCROLLSPY PLUGIN DEFINITION
1898
- // ===========================
1899
-
1900
- var old = $.fn.scrollspy
1901
-
1902
- $.fn.scrollspy = function (option) {
1903
- return this.each(function () {
1904
- var $this = $(this)
1905
- var data = $this.data('bs.scrollspy')
1906
- var options = typeof option == 'object' && option
1907
-
1908
- if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
1909
- if (typeof option == 'string') data[option]()
1910
- })
1911
- }
1912
-
1913
- $.fn.scrollspy.Constructor = ScrollSpy
1914
-
1915
-
1916
- // SCROLLSPY NO CONFLICT
1917
- // =====================
1918
-
1919
- $.fn.scrollspy.noConflict = function () {
1920
- $.fn.scrollspy = old
1921
- return this
1922
- }
1923
-
1924
-
1925
- // SCROLLSPY DATA-API
1926
- // ==================
1927
-
1928
- $(window).on('load', function () {
1929
- $('[data-spy="scroll"]').each(function () {
1930
- var $spy = $(this)
1931
- $spy.scrollspy($spy.data())
2316
+ Plugin.call($spy, data)
1932
2317
  })
1933
2318
  })
1934
2319
 
1935
- }(window.jQuery);
1936
-
1937
- /* ========================================================================
1938
- * Bootstrap: transition.js v3.0.0
1939
- * http://twbs.github.com/bootstrap/javascript.html#transitions
1940
- * ========================================================================
1941
- * Copyright 2013 Twitter, Inc.
1942
- *
1943
- * Licensed under the Apache License, Version 2.0 (the "License");
1944
- * you may not use this file except in compliance with the License.
1945
- * You may obtain a copy of the License at
1946
- *
1947
- * http://www.apache.org/licenses/LICENSE-2.0
1948
- *
1949
- * Unless required by applicable law or agreed to in writing, software
1950
- * distributed under the License is distributed on an "AS IS" BASIS,
1951
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1952
- * See the License for the specific language governing permissions and
1953
- * limitations under the License.
1954
- * ======================================================================== */
1955
-
1956
-
1957
- +function ($) { "use strict";
1958
-
1959
- // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
1960
- // ============================================================
1961
-
1962
- function transitionEnd() {
1963
- var el = document.createElement('bootstrap')
1964
-
1965
- var transEndEventNames = {
1966
- 'WebkitTransition' : 'webkitTransitionEnd'
1967
- , 'MozTransition' : 'transitionend'
1968
- , 'OTransition' : 'oTransitionEnd otransitionend'
1969
- , 'transition' : 'transitionend'
1970
- }
1971
-
1972
- for (var name in transEndEventNames) {
1973
- if (el.style[name] !== undefined) {
1974
- return { end: transEndEventNames[name] }
1975
- }
1976
- }
1977
- }
1978
-
1979
- // http://blog.alexmaccaw.com/css-transitions
1980
- $.fn.emulateTransitionEnd = function (duration) {
1981
- var called = false, $el = this
1982
- $(this).one($.support.transition.end, function () { called = true })
1983
- var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
1984
- setTimeout(callback, duration)
1985
- return this
1986
- }
1987
-
1988
- $(function () {
1989
- $.support.transition = transitionEnd()
1990
- })
1991
-
1992
- }(window.jQuery);
2320
+ }(jQuery);