locomotivecms_wagon 2.0.0.rc2 → 2.0.0.rc3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/generators/{bootstrap3 → bootstrap}/Gemfile.tt +0 -0
  4. data/generators/{bootstrap3 → bootstrap}/app/content_types/.empty_directory +0 -0
  5. data/generators/bootstrap/app/views/pages/404.liquid +18 -0
  6. data/generators/bootstrap/app/views/pages/404.liquid.haml +14 -0
  7. data/generators/bootstrap/app/views/pages/index.liquid +31 -0
  8. data/generators/bootstrap/app/views/pages/index.liquid.haml +25 -0
  9. data/generators/bootstrap/app/views/pages/layouts/default.liquid +31 -0
  10. data/generators/bootstrap/app/views/pages/layouts/default.liquid.haml +30 -0
  11. data/generators/bootstrap/app/views/pages/layouts/simple.liquid +36 -0
  12. data/generators/bootstrap/app/views/pages/layouts/simple.liquid.haml +29 -0
  13. data/generators/bootstrap/app/views/snippets/footer.liquid +5 -0
  14. data/generators/bootstrap/app/views/snippets/footer.liquid.haml +3 -0
  15. data/generators/bootstrap/app/views/snippets/nav.liquid +26 -0
  16. data/generators/bootstrap/app/views/snippets/nav.liquid.haml +19 -0
  17. data/generators/{bootstrap3 → bootstrap}/config/deploy.yml +0 -0
  18. data/generators/bootstrap/config/site.yml.tt +1 -6
  19. data/generators/{bootstrap3 → bootstrap}/config/translations.yml +0 -0
  20. data/generators/{bootstrap3 → bootstrap}/data/.empty_directory +0 -0
  21. data/generators/{bootstrap3 → bootstrap}/icon.png +0 -0
  22. data/generators/bootstrap/public/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  23. data/generators/bootstrap/public/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
  24. data/generators/bootstrap/public/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  25. data/generators/bootstrap/public/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  26. data/generators/bootstrap/public/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  27. data/generators/{bootstrap3/public/samples → bootstrap/public/images}/favicon.png +0 -0
  28. data/generators/bootstrap/public/javascripts/application.js +2 -0
  29. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/affix.js +60 -35
  30. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/alert.js +15 -9
  31. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/button.js +33 -20
  32. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/carousel.js +79 -47
  33. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/collapse.js +84 -43
  34. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/dropdown.js +64 -46
  35. data/generators/bootstrap/public/javascripts/bootstrap/modal.js +337 -0
  36. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/popover.js +12 -14
  37. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/scrollspy.js +57 -38
  38. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/tab.js +54 -24
  39. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/tooltip.js +202 -87
  40. data/generators/{bootstrap3 → bootstrap}/public/javascripts/bootstrap/transition.js +19 -8
  41. data/generators/bootstrap/public/javascripts/bootstrap.min.js +7 -0
  42. data/generators/bootstrap/public/javascripts/jquery.min.js +5 -0
  43. data/generators/bootstrap/public/stylesheets/application.css +7 -0
  44. data/generators/bootstrap/public/stylesheets/application.scss +7 -0
  45. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_alerts.scss +9 -3
  46. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_badges.scss +26 -13
  47. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_breadcrumbs.scss +3 -1
  48. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_button-groups.scss +32 -14
  49. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_buttons.scss +22 -13
  50. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_carousel.scss +43 -6
  51. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_close.scss +1 -0
  52. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_code.scss +7 -1
  53. data/generators/bootstrap/public/stylesheets/bootstrap/_component-animations.scss +37 -0
  54. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_dropdowns.scss +12 -9
  55. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_forms.scss +240 -65
  56. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_glyphicons.scss +83 -9
  57. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_grid.scss +4 -4
  58. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_input-groups.scss +7 -2
  59. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_jumbotron.scss +12 -4
  60. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_labels.scss +11 -9
  61. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_list-group.scss +32 -12
  62. data/generators/bootstrap/public/stylesheets/bootstrap/_media.scss +66 -0
  63. data/generators/bootstrap/public/stylesheets/bootstrap/_mixins.scss +40 -0
  64. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_modals.scss +18 -7
  65. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_navbar.scss +75 -33
  66. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_navs.scss +4 -4
  67. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_normalize.scss +29 -28
  68. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_pager.scss +2 -3
  69. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_pagination.scss +4 -3
  70. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_panels.scss +40 -10
  71. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_popovers.scss +6 -8
  72. data/generators/bootstrap/public/stylesheets/bootstrap/_print.scss +101 -0
  73. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_progress-bars.scss +13 -6
  74. data/generators/bootstrap/public/stylesheets/bootstrap/_responsive-embed.scss +35 -0
  75. data/generators/bootstrap/public/stylesheets/bootstrap/_responsive-utilities.scss +179 -0
  76. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_scaffolding.scss +31 -4
  77. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_tables.scss +17 -16
  78. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_theme.scss +57 -13
  79. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_thumbnails.scss +2 -2
  80. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_tooltip.scss +13 -7
  81. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_type.scss +38 -24
  82. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_utilities.scss +3 -4
  83. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_variables.scss +86 -47
  84. data/generators/{bootstrap3 → bootstrap}/public/stylesheets/bootstrap/_wells.scss +0 -0
  85. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_alerts.scss +14 -0
  86. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_background-variant.scss +12 -0
  87. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
  88. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_buttons.scss +68 -0
  89. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
  90. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
  91. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_forms.scss +88 -0
  92. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_gradients.scss +58 -0
  93. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
  94. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_grid.scss +122 -0
  95. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
  96. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_image.scss +33 -0
  97. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_labels.scss +12 -0
  98. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_list-group.scss +32 -0
  99. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
  100. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  101. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_opacity.scss +8 -0
  102. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_pagination.scss +24 -0
  103. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_panels.scss +24 -0
  104. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
  105. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
  106. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_reset-text.scss +18 -0
  107. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_resize.scss +6 -0
  108. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_responsive-visibility.scss +21 -0
  109. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_size.scss +10 -0
  110. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
  111. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
  112. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_text-emphasis.scss +12 -0
  113. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
  114. data/generators/bootstrap/public/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
  115. data/generators/bootstrap/public/stylesheets/bootstrap.css +5 -0
  116. data/generators/{bootstrap3/public/stylesheets/bootstrap.css.scss → bootstrap/public/stylesheets/bootstrap.scss} +16 -2
  117. data/lib/locomotive/wagon/cli.rb +3 -3
  118. data/lib/locomotive/wagon/commands/authenticate_command.rb +2 -1
  119. data/lib/locomotive/wagon/commands/concerns/spinner_concern.rb +29 -0
  120. data/lib/locomotive/wagon/commands/pull_command.rb +18 -3
  121. data/lib/locomotive/wagon/commands/push_command.rb +28 -4
  122. data/lib/locomotive/wagon/commands/sync_command.rb +21 -6
  123. data/lib/locomotive/wagon/commands/sync_sub_commands/sync_pages_command.rb +27 -3
  124. data/lib/locomotive/wagon/generators/site/{bootstrap3.rb → bootstrap.rb} +12 -6
  125. data/lib/locomotive/wagon/generators/site.rb +1 -1
  126. data/lib/locomotive/wagon/tools/listen.rb +1 -1
  127. data/lib/locomotive/wagon/version.rb +1 -1
  128. data/lib/locomotive/wagon.rb +2 -2
  129. data/locomotivecms_wagon.gemspec +3 -2
  130. data/spec/unit/decorators/theme_asset_decorator_spec.rb +10 -0
  131. metadata +124 -90
  132. data/generators/bootstrap3/app/views/pages/404.liquid +0 -13
  133. data/generators/bootstrap3/app/views/pages/404.liquid.haml +0 -10
  134. data/generators/bootstrap3/app/views/pages/index.liquid +0 -738
  135. data/generators/bootstrap3/app/views/pages/index.liquid.haml +0 -1018
  136. data/generators/bootstrap3/app/views/snippets/footer.liquid +0 -3
  137. data/generators/bootstrap3/app/views/snippets/footer.liquid.haml +0 -2
  138. data/generators/bootstrap3/config/site.yml.tt +0 -28
  139. data/generators/bootstrap3/public/fonts/glyphicons-halflings-regular.eot +0 -0
  140. data/generators/bootstrap3/public/fonts/glyphicons-halflings-regular.svg +0 -229
  141. data/generators/bootstrap3/public/fonts/glyphicons-halflings-regular.ttf +0 -0
  142. data/generators/bootstrap3/public/fonts/glyphicons-halflings-regular.woff +0 -0
  143. data/generators/bootstrap3/public/images/.empty_directory +0 -1
  144. data/generators/bootstrap3/public/javascripts/bootstrap/modal.js +0 -243
  145. data/generators/bootstrap3/public/javascripts/bootstrap.min.js +0 -12
  146. data/generators/bootstrap3/public/samples/apple-touch-icon-114x114-precomposed.png +0 -0
  147. data/generators/bootstrap3/public/samples/apple-touch-icon-144x144-precomposed.png +0 -0
  148. data/generators/bootstrap3/public/samples/apple-touch-icon-72x72-precomposed.png +0 -0
  149. data/generators/bootstrap3/public/samples/apple-touch-icon-precomposed.png +0 -0
  150. data/generators/bootstrap3/public/stylesheets/application.css +0 -1
  151. data/generators/bootstrap3/public/stylesheets/application.css.scss +0 -8
  152. data/generators/bootstrap3/public/stylesheets/bootstrap/_component-animations.scss +0 -29
  153. data/generators/bootstrap3/public/stylesheets/bootstrap/_media.scss +0 -56
  154. data/generators/bootstrap3/public/stylesheets/bootstrap/_mixins.scss +0 -947
  155. data/generators/bootstrap3/public/stylesheets/bootstrap/_print.scss +0 -101
  156. data/generators/bootstrap3/public/stylesheets/bootstrap/_responsive-utilities.scss +0 -74
  157. data/generators/bootstrap3/public/stylesheets/bootstrap/bootstrap.css.scss +0 -49
  158. data/generators/bootstrap3/public/stylesheets/bootstrap.css +0 -5784
  159. data/lib/locomotive/wagon/generators/site/bootstrap2.rb +0 -34
@@ -1,8 +1,8 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tab.js v3.1.1
2
+ * Bootstrap: tab.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#tabs
4
4
  * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
5
+ * Copyright 2011-2015 Twitter, Inc.
6
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
7
  * ======================================================================== */
8
8
 
@@ -14,9 +14,15 @@
14
14
  // ====================
15
15
 
16
16
  var Tab = function (element) {
17
+ // jscs:disable requireDollarBeforejQueryAssignment
17
18
  this.element = $(element)
19
+ // jscs:enable requireDollarBeforejQueryAssignment
18
20
  }
19
21
 
22
+ Tab.VERSION = '3.3.5'
23
+
24
+ Tab.TRANSITION_DURATION = 150
25
+
20
26
  Tab.prototype.show = function () {
21
27
  var $this = this.element
22
28
  var $ul = $this.closest('ul:not(.dropdown-menu)')
@@ -24,27 +30,35 @@
24
30
 
25
31
  if (!selector) {
26
32
  selector = $this.attr('href')
27
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
33
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
28
34
  }
29
35
 
30
36
  if ($this.parent('li').hasClass('active')) return
31
37
 
32
- var previous = $ul.find('.active:last a')[0]
33
- var e = $.Event('show.bs.tab', {
34
- relatedTarget: previous
38
+ var $previous = $ul.find('.active:last a')
39
+ var hideEvent = $.Event('hide.bs.tab', {
40
+ relatedTarget: $this[0]
41
+ })
42
+ var showEvent = $.Event('show.bs.tab', {
43
+ relatedTarget: $previous[0]
35
44
  })
36
45
 
37
- $this.trigger(e)
46
+ $previous.trigger(hideEvent)
47
+ $this.trigger(showEvent)
38
48
 
39
- if (e.isDefaultPrevented()) return
49
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
40
50
 
41
51
  var $target = $(selector)
42
52
 
43
- this.activate($this.parent('li'), $ul)
53
+ this.activate($this.closest('li'), $ul)
44
54
  this.activate($target, $target.parent(), function () {
55
+ $previous.trigger({
56
+ type: 'hidden.bs.tab',
57
+ relatedTarget: $this[0]
58
+ })
45
59
  $this.trigger({
46
60
  type: 'shown.bs.tab',
47
- relatedTarget: previous
61
+ relatedTarget: $previous[0]
48
62
  })
49
63
  })
50
64
  }
@@ -53,15 +67,21 @@
53
67
  var $active = container.find('> .active')
54
68
  var transition = callback
55
69
  && $.support.transition
56
- && $active.hasClass('fade')
70
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
57
71
 
58
72
  function next() {
59
73
  $active
60
74
  .removeClass('active')
61
75
  .find('> .dropdown-menu > .active')
62
- .removeClass('active')
76
+ .removeClass('active')
77
+ .end()
78
+ .find('[data-toggle="tab"]')
79
+ .attr('aria-expanded', false)
63
80
 
64
- element.addClass('active')
81
+ element
82
+ .addClass('active')
83
+ .find('[data-toggle="tab"]')
84
+ .attr('aria-expanded', true)
65
85
 
66
86
  if (transition) {
67
87
  element[0].offsetWidth // reflow for transition
@@ -70,17 +90,22 @@
70
90
  element.removeClass('fade')
71
91
  }
72
92
 
73
- if (element.parent('.dropdown-menu')) {
74
- element.closest('li.dropdown').addClass('active')
93
+ if (element.parent('.dropdown-menu').length) {
94
+ element
95
+ .closest('li.dropdown')
96
+ .addClass('active')
97
+ .end()
98
+ .find('[data-toggle="tab"]')
99
+ .attr('aria-expanded', true)
75
100
  }
76
101
 
77
102
  callback && callback()
78
103
  }
79
104
 
80
- transition ?
105
+ $active.length && transition ?
81
106
  $active
82
- .one($.support.transition.end, next)
83
- .emulateTransitionEnd(150) :
107
+ .one('bsTransitionEnd', next)
108
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
84
109
  next()
85
110
 
86
111
  $active.removeClass('in')
@@ -90,9 +115,7 @@
90
115
  // TAB PLUGIN DEFINITION
91
116
  // =====================
92
117
 
93
- var old = $.fn.tab
94
-
95
- $.fn.tab = function ( option ) {
118
+ function Plugin(option) {
96
119
  return this.each(function () {
97
120
  var $this = $(this)
98
121
  var data = $this.data('bs.tab')
@@ -102,6 +125,9 @@
102
125
  })
103
126
  }
104
127
 
128
+ var old = $.fn.tab
129
+
130
+ $.fn.tab = Plugin
105
131
  $.fn.tab.Constructor = Tab
106
132
 
107
133
 
@@ -117,9 +143,13 @@
117
143
  // TAB DATA-API
118
144
  // ============
119
145
 
120
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
146
+ var clickHandler = function (e) {
121
147
  e.preventDefault()
122
- $(this).tab('show')
123
- })
148
+ Plugin.call($(this), 'show')
149
+ }
150
+
151
+ $(document)
152
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
153
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
124
154
 
125
155
  }(jQuery);
@@ -1,9 +1,9 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tooltip.js v3.1.1
2
+ * Bootstrap: tooltip.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#tooltip
4
4
  * Inspired by the original jQuery.tipsy by Jason Frame
5
5
  * ========================================================================
6
- * Copyright 2011-2014 Twitter, Inc.
6
+ * Copyright 2011-2015 Twitter, Inc.
7
7
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8
8
  * ======================================================================== */
9
9
 
@@ -15,33 +15,48 @@
15
15
  // ===============================
16
16
 
17
17
  var Tooltip = function (element, options) {
18
- this.type =
19
- this.options =
20
- this.enabled =
21
- this.timeout =
22
- this.hoverState =
18
+ this.type = null
19
+ this.options = null
20
+ this.enabled = null
21
+ this.timeout = null
22
+ this.hoverState = null
23
23
  this.$element = null
24
+ this.inState = null
24
25
 
25
26
  this.init('tooltip', element, options)
26
27
  }
27
28
 
29
+ Tooltip.VERSION = '3.3.5'
30
+
31
+ Tooltip.TRANSITION_DURATION = 150
32
+
28
33
  Tooltip.DEFAULTS = {
29
34
  animation: true,
30
35
  placement: 'top',
31
36
  selector: false,
32
- template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
37
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
33
38
  trigger: 'hover focus',
34
39
  title: '',
35
40
  delay: 0,
36
41
  html: false,
37
- container: false
42
+ container: false,
43
+ viewport: {
44
+ selector: 'body',
45
+ padding: 0
46
+ }
38
47
  }
39
48
 
40
49
  Tooltip.prototype.init = function (type, element, options) {
41
- this.enabled = true
42
- this.type = type
43
- this.$element = $(element)
44
- this.options = this.getOptions(options)
50
+ this.enabled = true
51
+ this.type = type
52
+ this.$element = $(element)
53
+ this.options = this.getOptions(options)
54
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
55
+ this.inState = { click: false, hover: false, focus: false }
56
+
57
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
58
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
59
+ }
45
60
 
46
61
  var triggers = this.options.trigger.split(' ')
47
62
 
@@ -94,7 +109,21 @@
94
109
 
95
110
  Tooltip.prototype.enter = function (obj) {
96
111
  var self = obj instanceof this.constructor ?
97
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
112
+ obj : $(obj.currentTarget).data('bs.' + this.type)
113
+
114
+ if (!self) {
115
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
116
+ $(obj.currentTarget).data('bs.' + this.type, self)
117
+ }
118
+
119
+ if (obj instanceof $.Event) {
120
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
121
+ }
122
+
123
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
124
+ self.hoverState = 'in'
125
+ return
126
+ }
98
127
 
99
128
  clearTimeout(self.timeout)
100
129
 
@@ -107,9 +136,28 @@
107
136
  }, self.options.delay.show)
108
137
  }
109
138
 
139
+ Tooltip.prototype.isInStateTrue = function () {
140
+ for (var key in this.inState) {
141
+ if (this.inState[key]) return true
142
+ }
143
+
144
+ return false
145
+ }
146
+
110
147
  Tooltip.prototype.leave = function (obj) {
111
148
  var self = obj instanceof this.constructor ?
112
- obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)
149
+ obj : $(obj.currentTarget).data('bs.' + this.type)
150
+
151
+ if (!self) {
152
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
153
+ $(obj.currentTarget).data('bs.' + this.type, self)
154
+ }
155
+
156
+ if (obj instanceof $.Event) {
157
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
158
+ }
159
+
160
+ if (self.isInStateTrue()) return
113
161
 
114
162
  clearTimeout(self.timeout)
115
163
 
@@ -128,12 +176,17 @@
128
176
  if (this.hasContent() && this.enabled) {
129
177
  this.$element.trigger(e)
130
178
 
131
- if (e.isDefaultPrevented()) return
132
- var that = this;
179
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
180
+ if (e.isDefaultPrevented() || !inDom) return
181
+ var that = this
133
182
 
134
183
  var $tip = this.tip()
135
184
 
185
+ var tipId = this.getUID(this.type)
186
+
136
187
  this.setContent()
188
+ $tip.attr('id', tipId)
189
+ this.$element.attr('aria-describedby', tipId)
137
190
 
138
191
  if (this.options.animation) $tip.addClass('fade')
139
192
 
@@ -149,26 +202,23 @@
149
202
  .detach()
150
203
  .css({ top: 0, left: 0, display: 'block' })
151
204
  .addClass(placement)
205
+ .data('bs.' + this.type, this)
152
206
 
153
207
  this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
208
+ this.$element.trigger('inserted.bs.' + this.type)
154
209
 
155
210
  var pos = this.getPosition()
156
211
  var actualWidth = $tip[0].offsetWidth
157
212
  var actualHeight = $tip[0].offsetHeight
158
213
 
159
214
  if (autoPlace) {
160
- var $parent = this.$element.parent()
161
-
162
215
  var orgPlacement = placement
163
- var docScroll = document.documentElement.scrollTop || document.body.scrollTop
164
- var parentWidth = this.options.container == 'body' ? window.innerWidth : $parent.outerWidth()
165
- var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()
166
- var parentLeft = this.options.container == 'body' ? 0 : $parent.offset().left
167
-
168
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - docScroll > parentHeight ? 'top' :
169
- placement == 'top' && pos.top - docScroll - actualHeight < 0 ? 'bottom' :
170
- placement == 'right' && pos.right + actualWidth > parentWidth ? 'left' :
171
- placement == 'left' && pos.left - actualWidth < parentLeft ? 'right' :
216
+ var viewportDim = this.getPosition(this.$viewport)
217
+
218
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
219
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
220
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
221
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
172
222
  placement
173
223
 
174
224
  $tip
@@ -179,22 +229,24 @@
179
229
  var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
180
230
 
181
231
  this.applyPlacement(calculatedOffset, placement)
182
- this.hoverState = null
183
232
 
184
- var complete = function() {
233
+ var complete = function () {
234
+ var prevHoverState = that.hoverState
185
235
  that.$element.trigger('shown.bs.' + that.type)
236
+ that.hoverState = null
237
+
238
+ if (prevHoverState == 'out') that.leave(that)
186
239
  }
187
240
 
188
241
  $.support.transition && this.$tip.hasClass('fade') ?
189
242
  $tip
190
- .one($.support.transition.end, complete)
191
- .emulateTransitionEnd(150) :
243
+ .one('bsTransitionEnd', complete)
244
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
192
245
  complete()
193
246
  }
194
247
  }
195
248
 
196
249
  Tooltip.prototype.applyPlacement = function (offset, placement) {
197
- var replace
198
250
  var $tip = this.tip()
199
251
  var width = $tip[0].offsetWidth
200
252
  var height = $tip[0].offsetHeight
@@ -207,8 +259,8 @@
207
259
  if (isNaN(marginTop)) marginTop = 0
208
260
  if (isNaN(marginLeft)) marginLeft = 0
209
261
 
210
- offset.top = offset.top + marginTop
211
- offset.left = offset.left + marginLeft
262
+ offset.top += marginTop
263
+ offset.left += marginLeft
212
264
 
213
265
  // $.fn.offset doesn't round pixel values
214
266
  // so we use setOffset directly with our own function B-0
@@ -228,33 +280,26 @@
228
280
  var actualHeight = $tip[0].offsetHeight
229
281
 
230
282
  if (placement == 'top' && actualHeight != height) {
231
- replace = true
232
283
  offset.top = offset.top + height - actualHeight
233
284
  }
234
285
 
235
- if (/bottom|top/.test(placement)) {
236
- var delta = 0
286
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
237
287
 
238
- if (offset.left < 0) {
239
- delta = offset.left * -2
240
- offset.left = 0
288
+ if (delta.left) offset.left += delta.left
289
+ else offset.top += delta.top
241
290
 
242
- $tip.offset(offset)
291
+ var isVertical = /top|bottom/.test(placement)
292
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
293
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
243
294
 
244
- actualWidth = $tip[0].offsetWidth
245
- actualHeight = $tip[0].offsetHeight
246
- }
247
-
248
- this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
249
- } else {
250
- this.replaceArrow(actualHeight - height, actualHeight, 'top')
251
- }
252
-
253
- if (replace) $tip.offset(offset)
295
+ $tip.offset(offset)
296
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
254
297
  }
255
298
 
256
- Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
257
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
299
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
300
+ this.arrow()
301
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
302
+ .css(isVertical ? 'top' : 'left', '')
258
303
  }
259
304
 
260
305
  Tooltip.prototype.setContent = function () {
@@ -265,14 +310,17 @@
265
310
  $tip.removeClass('fade in top bottom left right')
266
311
  }
267
312
 
268
- Tooltip.prototype.hide = function () {
313
+ Tooltip.prototype.hide = function (callback) {
269
314
  var that = this
270
- var $tip = this.tip()
315
+ var $tip = $(this.$tip)
271
316
  var e = $.Event('hide.bs.' + this.type)
272
317
 
273
318
  function complete() {
274
319
  if (that.hoverState != 'in') $tip.detach()
275
- that.$element.trigger('hidden.bs.' + that.type)
320
+ that.$element
321
+ .removeAttr('aria-describedby')
322
+ .trigger('hidden.bs.' + that.type)
323
+ callback && callback()
276
324
  }
277
325
 
278
326
  this.$element.trigger(e)
@@ -281,10 +329,10 @@
281
329
 
282
330
  $tip.removeClass('in')
283
331
 
284
- $.support.transition && this.$tip.hasClass('fade') ?
332
+ $.support.transition && $tip.hasClass('fade') ?
285
333
  $tip
286
- .one($.support.transition.end, complete)
287
- .emulateTransitionEnd(150) :
334
+ .one('bsTransitionEnd', complete)
335
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
288
336
  complete()
289
337
 
290
338
  this.hoverState = null
@@ -294,7 +342,7 @@
294
342
 
295
343
  Tooltip.prototype.fixTitle = function () {
296
344
  var $e = this.$element
297
- if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
345
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
298
346
  $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
299
347
  }
300
348
  }
@@ -303,19 +351,58 @@
303
351
  return this.getTitle()
304
352
  }
305
353
 
306
- Tooltip.prototype.getPosition = function () {
307
- var el = this.$element[0]
308
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
309
- width: el.offsetWidth,
310
- height: el.offsetHeight
311
- }, this.$element.offset())
354
+ Tooltip.prototype.getPosition = function ($element) {
355
+ $element = $element || this.$element
356
+
357
+ var el = $element[0]
358
+ var isBody = el.tagName == 'BODY'
359
+
360
+ var elRect = el.getBoundingClientRect()
361
+ if (elRect.width == null) {
362
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
363
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
364
+ }
365
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
366
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
367
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
368
+
369
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
312
370
  }
313
371
 
314
372
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
315
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
316
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
373
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
374
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
317
375
  placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
318
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
376
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
377
+
378
+ }
379
+
380
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
381
+ var delta = { top: 0, left: 0 }
382
+ if (!this.$viewport) return delta
383
+
384
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
385
+ var viewportDimensions = this.getPosition(this.$viewport)
386
+
387
+ if (/right|left/.test(placement)) {
388
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
389
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
390
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
391
+ delta.top = viewportDimensions.top - topEdgeOffset
392
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
393
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
394
+ }
395
+ } else {
396
+ var leftEdgeOffset = pos.left - viewportPadding
397
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
398
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
399
+ delta.left = viewportDimensions.left - leftEdgeOffset
400
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
401
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
402
+ }
403
+ }
404
+
405
+ return delta
319
406
  }
320
407
 
321
408
  Tooltip.prototype.getTitle = function () {
@@ -329,20 +416,24 @@
329
416
  return title
330
417
  }
331
418
 
332
- Tooltip.prototype.tip = function () {
333
- return this.$tip = this.$tip || $(this.options.template)
419
+ Tooltip.prototype.getUID = function (prefix) {
420
+ do prefix += ~~(Math.random() * 1000000)
421
+ while (document.getElementById(prefix))
422
+ return prefix
334
423
  }
335
424
 
336
- Tooltip.prototype.arrow = function () {
337
- return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
425
+ Tooltip.prototype.tip = function () {
426
+ if (!this.$tip) {
427
+ this.$tip = $(this.options.template)
428
+ if (this.$tip.length != 1) {
429
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
430
+ }
431
+ }
432
+ return this.$tip
338
433
  }
339
434
 
340
- Tooltip.prototype.validate = function () {
341
- if (!this.$element[0].parentNode) {
342
- this.hide()
343
- this.$element = null
344
- this.options = null
345
- }
435
+ Tooltip.prototype.arrow = function () {
436
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
346
437
  }
347
438
 
348
439
  Tooltip.prototype.enable = function () {
@@ -358,33 +449,57 @@
358
449
  }
359
450
 
360
451
  Tooltip.prototype.toggle = function (e) {
361
- var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this
362
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
452
+ var self = this
453
+ if (e) {
454
+ self = $(e.currentTarget).data('bs.' + this.type)
455
+ if (!self) {
456
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
457
+ $(e.currentTarget).data('bs.' + this.type, self)
458
+ }
459
+ }
460
+
461
+ if (e) {
462
+ self.inState.click = !self.inState.click
463
+ if (self.isInStateTrue()) self.enter(self)
464
+ else self.leave(self)
465
+ } else {
466
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
467
+ }
363
468
  }
364
469
 
365
470
  Tooltip.prototype.destroy = function () {
471
+ var that = this
366
472
  clearTimeout(this.timeout)
367
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
473
+ this.hide(function () {
474
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
475
+ if (that.$tip) {
476
+ that.$tip.detach()
477
+ }
478
+ that.$tip = null
479
+ that.$arrow = null
480
+ that.$viewport = null
481
+ })
368
482
  }
369
483
 
370
484
 
371
485
  // TOOLTIP PLUGIN DEFINITION
372
486
  // =========================
373
487
 
374
- var old = $.fn.tooltip
375
-
376
- $.fn.tooltip = function (option) {
488
+ function Plugin(option) {
377
489
  return this.each(function () {
378
490
  var $this = $(this)
379
491
  var data = $this.data('bs.tooltip')
380
492
  var options = typeof option == 'object' && option
381
493
 
382
- if (!data && option == 'destroy') return
494
+ if (!data && /destroy|hide/.test(option)) return
383
495
  if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
384
496
  if (typeof option == 'string') data[option]()
385
497
  })
386
498
  }
387
499
 
500
+ var old = $.fn.tooltip
501
+
502
+ $.fn.tooltip = Plugin
388
503
  $.fn.tooltip.Constructor = Tooltip
389
504
 
390
505