twitter-bootstrap-rails 2.2.1 → 2.2.3

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.

Potentially problematic release.


This version of twitter-bootstrap-rails might be problematic. Click here for more details.

Files changed (46) hide show
  1. data/README.md +4 -0
  2. data/lib/generators/bootstrap/themed/themed_generator.rb +1 -1
  3. data/lib/twitter/bootstrap/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-affix.js +1 -1
  5. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-alert.js +1 -1
  6. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-button.js +1 -1
  7. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-carousel.js +31 -9
  8. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-collapse.js +4 -4
  9. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-dropdown.js +14 -10
  10. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-modal.js +13 -11
  11. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-popover.js +5 -5
  12. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-scrollspy.js +2 -2
  13. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tab.js +1 -1
  14. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-tooltip.js +95 -29
  15. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-transition.js +1 -1
  16. data/vendor/assets/javascripts/twitter/bootstrap/bootstrap-typeahead.js +16 -4
  17. data/vendor/assets/stylesheets/twitter-bootstrap-static/bootstrap.css.erb +108 -103
  18. data/vendor/assets/stylesheets/twitter-bootstrap-static/sprites.css.erb +2 -2
  19. data/vendor/toolkit/twitter/bootstrap/bootstrap.less +4 -4
  20. data/vendor/toolkit/twitter/bootstrap/button-groups.less +4 -2
  21. data/vendor/toolkit/twitter/bootstrap/buttons.less +8 -10
  22. data/vendor/toolkit/twitter/bootstrap/carousel.less +34 -7
  23. data/vendor/toolkit/twitter/bootstrap/close.less +2 -1
  24. data/vendor/toolkit/twitter/bootstrap/dropdowns.less +16 -12
  25. data/vendor/toolkit/twitter/bootstrap/forms.less +5 -2
  26. data/vendor/toolkit/twitter/bootstrap/labels-badges.less +4 -2
  27. data/vendor/toolkit/twitter/bootstrap/media.less +2 -2
  28. data/vendor/toolkit/twitter/bootstrap/mixins.less +20 -4
  29. data/vendor/toolkit/twitter/bootstrap/navbar.less +20 -13
  30. data/vendor/toolkit/twitter/bootstrap/navs.less +39 -21
  31. data/vendor/toolkit/twitter/bootstrap/pager.less +3 -1
  32. data/vendor/toolkit/twitter/bootstrap/pagination.less +3 -1
  33. data/vendor/toolkit/twitter/bootstrap/popovers.less +5 -1
  34. data/vendor/toolkit/twitter/bootstrap/reset.less +1 -1
  35. data/vendor/toolkit/twitter/bootstrap/responsive-767px-max.less +2 -2
  36. data/vendor/toolkit/twitter/bootstrap/responsive-navbar.less +6 -2
  37. data/vendor/toolkit/twitter/bootstrap/responsive-utilities.less +16 -0
  38. data/vendor/toolkit/twitter/bootstrap/responsive.less +1 -10
  39. data/vendor/toolkit/twitter/bootstrap/scaffolding.less +2 -1
  40. data/vendor/toolkit/twitter/bootstrap/sprites.less +9 -5
  41. data/vendor/toolkit/twitter/bootstrap/tables.less +24 -17
  42. data/vendor/toolkit/twitter/bootstrap/thumbnails.less +3 -2
  43. data/vendor/toolkit/twitter/bootstrap/tooltip.less +6 -6
  44. data/vendor/toolkit/twitter/bootstrap/type.less +19 -7
  45. data/vendor/toolkit/twitter/bootstrap/variables.less +1 -1
  46. metadata +14 -14
data/README.md CHANGED
@@ -305,11 +305,15 @@ for handling flash messages, even if those messages are blank. See https://githu
305
305
  <li>Released gem v.2.1.9</li>
306
306
  <li>Released gem v.2.2.0 (Font Awesome 3)</li>
307
307
  <li>Released gem v.2.2.1 (minor fixes and updates)</li>
308
+ <li>Released gem v.2.2.2 (Bootstrap 2.3.0)</li>
309
+ <li>Released gem v.2.2.3 (Minor fixes)</li>
310
+
308
311
  </ul>
309
312
 
310
313
 
311
314
  ## Contributors & Patches & Forks
312
315
  <ul>
316
+ <li>Ben Lovell</li>
313
317
  <li>Daniel Morris</li>
314
318
  <li>Bradly Feeley</li>
315
319
  <li>Guilherme Moreira</li>
@@ -82,7 +82,7 @@ module Bootstrap
82
82
  end
83
83
 
84
84
  def retrieve_columns
85
- if defined?(ActiveRecord)
85
+ if defined?(ActiveRecord) == "constant" && ActiveRecord.class == Class
86
86
  rescue_block ActiveRecord::StatementInvalid do
87
87
  @model_name.constantize.columns
88
88
  end
@@ -1,7 +1,7 @@
1
1
  module Twitter
2
2
  module Bootstrap
3
3
  module Rails
4
- VERSION = "2.2.1"
4
+ VERSION = "2.2.3"
5
5
  end
6
6
  end
7
- end
7
+ end
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================
2
- * bootstrap-affix.js v2.2.2
2
+ * bootstrap-affix.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#affix
4
4
  * ==========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================
2
- * bootstrap-alert.js v2.2.2
2
+ * bootstrap-alert.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#alerts
4
4
  * ==========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -1,5 +1,5 @@
1
1
  /* ============================================================
2
- * bootstrap-button.js v2.2.2
2
+ * bootstrap-button.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#buttons
4
4
  * ============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -1,5 +1,5 @@
1
1
  /* ==========================================================
2
- * bootstrap-carousel.js v2.2.2
2
+ * bootstrap-carousel.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#carousel
4
4
  * ==========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -28,6 +28,7 @@
28
28
 
29
29
  var Carousel = function (element, options) {
30
30
  this.$element = $(element)
31
+ this.$indicators = this.$element.find('.carousel-indicators')
31
32
  this.options = options
32
33
  this.options.pause == 'hover' && this.$element
33
34
  .on('mouseenter', $.proxy(this.pause, this))
@@ -38,19 +39,24 @@
38
39
 
39
40
  cycle: function (e) {
40
41
  if (!e) this.paused = false
42
+ if (this.interval) clearInterval(this.interval);
41
43
  this.options.interval
42
44
  && !this.paused
43
45
  && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
44
46
  return this
45
47
  }
46
48
 
49
+ , getActiveIndex: function () {
50
+ this.$active = this.$element.find('.item.active')
51
+ this.$items = this.$active.parent().children()
52
+ return this.$items.index(this.$active)
53
+ }
54
+
47
55
  , to: function (pos) {
48
- var $active = this.$element.find('.item.active')
49
- , children = $active.parent().children()
50
- , activePos = children.index($active)
56
+ var activeIndex = this.getActiveIndex()
51
57
  , that = this
52
58
 
53
- if (pos > (children.length - 1) || pos < 0) return
59
+ if (pos > (this.$items.length - 1) || pos < 0) return
54
60
 
55
61
  if (this.sliding) {
56
62
  return this.$element.one('slid', function () {
@@ -58,11 +64,11 @@
58
64
  })
59
65
  }
60
66
 
61
- if (activePos == pos) {
67
+ if (activeIndex == pos) {
62
68
  return this.pause().cycle()
63
69
  }
64
70
 
65
- return this.slide(pos > activePos ? 'next' : 'prev', $(children[pos]))
71
+ return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
66
72
  }
67
73
 
68
74
  , pause: function (e) {
@@ -103,10 +109,19 @@
103
109
 
104
110
  e = $.Event('slide', {
105
111
  relatedTarget: $next[0]
112
+ , direction: direction
106
113
  })
107
114
 
108
115
  if ($next.hasClass('active')) return
109
116
 
117
+ if (this.$indicators.length) {
118
+ this.$indicators.find('.active').removeClass('active')
119
+ this.$element.one('slid', function () {
120
+ var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])
121
+ $nextIndicator && $nextIndicator.addClass('active')
122
+ })
123
+ }
124
+
110
125
  if ($.support.transition && this.$element.hasClass('slide')) {
111
126
  this.$element.trigger(e)
112
127
  if (e.isDefaultPrevented()) return
@@ -151,7 +166,7 @@
151
166
  if (!data) $this.data('carousel', (data = new Carousel(this, options)))
152
167
  if (typeof option == 'number') data.to(option)
153
168
  else if (action) data[action]()
154
- else if (options.interval) data.cycle()
169
+ else if (options.interval) data.pause().cycle()
155
170
  })
156
171
  }
157
172
 
@@ -174,11 +189,18 @@
174
189
  /* CAROUSEL DATA-API
175
190
  * ================= */
176
191
 
177
- $(document).on('click.carousel.data-api', '[data-slide]', function (e) {
192
+ $(document).on('click.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
178
193
  var $this = $(this), href
179
194
  , $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
180
195
  , options = $.extend({}, $target.data(), $this.data())
196
+ , slideIndex
197
+
181
198
  $target.carousel(options)
199
+
200
+ if (slideIndex = $this.attr('data-slide-to')) {
201
+ $target.data('carousel').pause().to(slideIndex).cycle()
202
+ }
203
+
182
204
  e.preventDefault()
183
205
  })
184
206
 
@@ -1,5 +1,5 @@
1
1
  /* =============================================================
2
- * bootstrap-collapse.js v2.2.2
2
+ * bootstrap-collapse.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#collapse
4
4
  * =============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -52,7 +52,7 @@
52
52
  , actives
53
53
  , hasData
54
54
 
55
- if (this.transitioning) return
55
+ if (this.transitioning || this.$element.hasClass('in')) return
56
56
 
57
57
  dimension = this.dimension()
58
58
  scroll = $.camelCase(['scroll', dimension].join('-'))
@@ -72,7 +72,7 @@
72
72
 
73
73
  , hide: function () {
74
74
  var dimension
75
- if (this.transitioning) return
75
+ if (this.transitioning || !this.$element.hasClass('in')) return
76
76
  dimension = this.dimension()
77
77
  this.reset(this.$element[dimension]())
78
78
  this.transition('removeClass', $.Event('hide'), 'hidden')
@@ -129,7 +129,7 @@
129
129
  return this.each(function () {
130
130
  var $this = $(this)
131
131
  , data = $this.data('collapse')
132
- , options = typeof option == 'object' && option
132
+ , options = $.extend({}, $.fn.collapse.defaults, $this.data(), typeof option == 'object' && option)
133
133
  if (!data) $this.data('collapse', (data = new Collapse(this, options)))
134
134
  if (typeof option == 'string') data[option]()
135
135
  })
@@ -1,5 +1,5 @@
1
1
  /* ============================================================
2
- * bootstrap-dropdown.js v2.2.2
2
+ * bootstrap-dropdown.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#dropdowns
4
4
  * ============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -81,7 +81,10 @@
81
81
 
82
82
  isActive = $parent.hasClass('open')
83
83
 
84
- if (!isActive || (isActive && e.keyCode == 27)) return $this.click()
84
+ if (!isActive || (isActive && e.keyCode == 27)) {
85
+ if (e.which == 27) $parent.find(toggle).focus()
86
+ return $this.click()
87
+ }
85
88
 
86
89
  $items = $('[role=menu] li:not(.divider):visible a', $parent)
87
90
 
@@ -115,8 +118,9 @@
115
118
  selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
116
119
  }
117
120
 
118
- $parent = $(selector)
119
- $parent.length || ($parent = $this.parent())
121
+ $parent = selector && $(selector)
122
+
123
+ if (!$parent || !$parent.length) $parent = $this.parent()
120
124
 
121
125
  return $parent
122
126
  }
@@ -152,10 +156,10 @@
152
156
  * =================================== */
153
157
 
154
158
  $(document)
155
- .on('click.dropdown.data-api touchstart.dropdown.data-api', clearMenus)
156
- .on('click.dropdown touchstart.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
157
- .on('touchstart.dropdown.data-api', '.dropdown-menu', function (e) { e.stopPropagation() })
158
- .on('click.dropdown.data-api touchstart.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
159
- .on('keydown.dropdown.data-api touchstart.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
159
+ .on('click.dropdown.data-api', clearMenus)
160
+ .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
161
+ .on('.dropdown-menu', function (e) { e.stopPropagation() })
162
+ .on('click.dropdown.data-api' , toggle, Dropdown.prototype.toggle)
163
+ .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)
160
164
 
161
- }(window.jQuery);
165
+ }(window.jQuery);
@@ -1,5 +1,5 @@
1
1
  /* =========================================================
2
- * bootstrap-modal.js v2.2.2
2
+ * bootstrap-modal.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#modals
4
4
  * =========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -60,8 +60,7 @@
60
60
  that.$element.appendTo(document.body) //don't move modals dom position
61
61
  }
62
62
 
63
- that.$element
64
- .show()
63
+ that.$element.show()
65
64
 
66
65
  if (transition) {
67
66
  that.$element[0].offsetWidth // force reflow
@@ -139,12 +138,13 @@
139
138
  })
140
139
  }
141
140
 
142
- , hideModal: function (that) {
143
- this.$element
144
- .hide()
145
- .trigger('hidden')
146
-
147
- this.backdrop()
141
+ , hideModal: function () {
142
+ var that = this
143
+ this.$element.hide()
144
+ this.backdrop(function () {
145
+ that.removeBackdrop()
146
+ that.$element.trigger('hidden')
147
+ })
148
148
  }
149
149
 
150
150
  , removeBackdrop: function () {
@@ -172,6 +172,8 @@
172
172
 
173
173
  this.$backdrop.addClass('in')
174
174
 
175
+ if (!callback) return
176
+
175
177
  doAnimate ?
176
178
  this.$backdrop.one($.support.transition.end, callback) :
177
179
  callback()
@@ -180,8 +182,8 @@
180
182
  this.$backdrop.removeClass('in')
181
183
 
182
184
  $.support.transition && this.$element.hasClass('fade')?
183
- this.$backdrop.one($.support.transition.end, $.proxy(this.removeBackdrop, this)) :
184
- this.removeBackdrop()
185
+ this.$backdrop.one($.support.transition.end, callback) :
186
+ callback()
185
187
 
186
188
  } else if (callback) {
187
189
  callback()
@@ -1,5 +1,5 @@
1
1
  /* ===========================================================
2
- * bootstrap-popover.js v2.2.2
2
+ * bootstrap-popover.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#popovers
4
4
  * ===========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -58,8 +58,8 @@
58
58
  , $e = this.$element
59
59
  , o = this.options
60
60
 
61
- content = $e.attr('data-content')
62
- || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
61
+ content = (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)
62
+ || $e.attr('data-content')
63
63
 
64
64
  return content
65
65
  }
@@ -99,7 +99,7 @@
99
99
  placement: 'right'
100
100
  , trigger: 'click'
101
101
  , content: ''
102
- , template: '<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"></div></div></div>'
102
+ , template: '<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
103
103
  })
104
104
 
105
105
 
@@ -111,4 +111,4 @@
111
111
  return this
112
112
  }
113
113
 
114
- }(window.jQuery);
114
+ }(window.jQuery);
@@ -1,5 +1,5 @@
1
1
  /* =============================================================
2
- * bootstrap-scrollspy.js v2.2.2
2
+ * bootstrap-scrollspy.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#scrollspy
4
4
  * =============================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -59,7 +59,7 @@
59
59
  , $href = /^#\w/.test(href) && $(href)
60
60
  return ( $href
61
61
  && $href.length
62
- && [[ $href.position().top + self.$scrollElement.scrollTop(), href ]] ) || null
62
+ && [[ $href.position().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]] ) || null
63
63
  })
64
64
  .sort(function (a, b) { return a[0] - b[0] })
65
65
  .each(function () {
@@ -1,5 +1,5 @@
1
1
  /* ========================================================
2
- * bootstrap-tab.js v2.2.2
2
+ * bootstrap-tab.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#tabs
4
4
  * ========================================================
5
5
  * Copyright 2012 Twitter, Inc.
@@ -1,5 +1,5 @@
1
1
  /* ===========================================================
2
- * bootstrap-tooltip.js v2.2.2
2
+ * bootstrap-tooltip.js v2.3.0
3
3
  * http://twitter.github.com/bootstrap/javascript.html#tooltips
4
4
  * Inspired by the original jQuery.tipsy by Jason Frame
5
5
  * ===========================================================
@@ -38,19 +38,27 @@
38
38
  , init: function (type, element, options) {
39
39
  var eventIn
40
40
  , eventOut
41
+ , triggers
42
+ , trigger
43
+ , i
41
44
 
42
45
  this.type = type
43
46
  this.$element = $(element)
44
47
  this.options = this.getOptions(options)
45
48
  this.enabled = true
46
49
 
47
- if (this.options.trigger == 'click') {
48
- this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
49
- } else if (this.options.trigger != 'manual') {
50
- eventIn = this.options.trigger == 'hover' ? 'mouseenter' : 'focus'
51
- eventOut = this.options.trigger == 'hover' ? 'mouseleave' : 'blur'
52
- this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
53
- this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
50
+ triggers = this.options.trigger.split(' ')
51
+
52
+ for (i = triggers.length; i--;) {
53
+ trigger = triggers[i]
54
+ if (trigger == 'click') {
55
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
56
+ } else if (trigger != 'manual') {
57
+ eventIn = trigger == 'hover' ? 'mouseenter' : 'focus'
58
+ eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'
59
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
60
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
61
+ }
54
62
  }
55
63
 
56
64
  this.options.selector ?
@@ -59,7 +67,7 @@
59
67
  }
60
68
 
61
69
  , getOptions: function (options) {
62
- options = $.extend({}, $.fn[this.type].defaults, options, this.$element.data())
70
+ options = $.extend({}, $.fn[this.type].defaults, this.$element.data(), options)
63
71
 
64
72
  if (options.delay && typeof options.delay == 'number') {
65
73
  options.delay = {
@@ -97,14 +105,16 @@
97
105
 
98
106
  , show: function () {
99
107
  var $tip
100
- , inside
101
108
  , pos
102
109
  , actualWidth
103
110
  , actualHeight
104
111
  , placement
105
112
  , tp
113
+ , e = $.Event('show')
106
114
 
107
115
  if (this.hasContent() && this.enabled) {
116
+ this.$element.trigger(e)
117
+ if (e.isDefaultPrevented()) return
108
118
  $tip = this.tip()
109
119
  this.setContent()
110
120
 
@@ -116,19 +126,18 @@
116
126
  this.options.placement.call(this, $tip[0], this.$element[0]) :
117
127
  this.options.placement
118
128
 
119
- inside = /in/.test(placement)
120
-
121
129
  $tip
122
130
  .detach()
123
131
  .css({ top: 0, left: 0, display: 'block' })
124
- .insertAfter(this.$element)
125
132
 
126
- pos = this.getPosition(inside)
133
+ this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
134
+
135
+ pos = this.getPosition()
127
136
 
128
137
  actualWidth = $tip[0].offsetWidth
129
138
  actualHeight = $tip[0].offsetHeight
130
139
 
131
- switch (inside ? placement.split(' ')[1] : placement) {
140
+ switch (placement) {
132
141
  case 'bottom':
133
142
  tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}
134
143
  break
@@ -143,11 +152,56 @@
143
152
  break
144
153
  }
145
154
 
146
- $tip
147
- .offset(tp)
148
- .addClass(placement)
149
- .addClass('in')
155
+ this.applyPlacement(tp, placement)
156
+ this.$element.trigger('shown')
157
+ }
158
+ }
159
+
160
+ , applyPlacement: function(offset, placement){
161
+ var $tip = this.tip()
162
+ , width = $tip[0].offsetWidth
163
+ , height = $tip[0].offsetHeight
164
+ , actualWidth
165
+ , actualHeight
166
+ , delta
167
+ , replace
168
+
169
+ $tip
170
+ .offset(offset)
171
+ .addClass(placement)
172
+ .addClass('in')
173
+
174
+ actualWidth = $tip[0].offsetWidth
175
+ actualHeight = $tip[0].offsetHeight
176
+
177
+ if (placement == 'top' && actualHeight != height) {
178
+ offset.top = offset.top + height - actualHeight
179
+ replace = true
150
180
  }
181
+
182
+ if (placement == 'bottom' || placement == 'top') {
183
+ delta = 0
184
+
185
+ if (offset.left < 0){
186
+ delta = offset.left * -2
187
+ offset.left = 0
188
+ $tip.offset(offset)
189
+ actualWidth = $tip[0].offsetWidth
190
+ actualHeight = $tip[0].offsetHeight
191
+ }
192
+
193
+ this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')
194
+ } else {
195
+ this.replaceArrow(actualHeight - height, actualHeight, 'top')
196
+ }
197
+
198
+ if (replace) $tip.offset(offset)
199
+ }
200
+
201
+ , replaceArrow: function(delta, dimension, position){
202
+ this
203
+ .arrow()
204
+ .css(position, delta ? (50 * (1 - delta / dimension) + "%") : '')
151
205
  }
152
206
 
153
207
  , setContent: function () {
@@ -161,6 +215,10 @@
161
215
  , hide: function () {
162
216
  var that = this
163
217
  , $tip = this.tip()
218
+ , e = $.Event('hide')
219
+
220
+ this.$element.trigger(e)
221
+ if (e.isDefaultPrevented()) return
164
222
 
165
223
  $tip.removeClass('in')
166
224
 
@@ -179,13 +237,15 @@
179
237
  removeWithAnimation() :
180
238
  $tip.detach()
181
239
 
240
+ this.$element.trigger('hidden')
241
+
182
242
  return this
183
243
  }
184
244
 
185
245
  , fixTitle: function () {
186
246
  var $e = this.$element
187
247
  if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
188
- $e.attr('data-original-title', $e.attr('title') || '').removeAttr('title')
248
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
189
249
  }
190
250
  }
191
251
 
@@ -193,11 +253,12 @@
193
253
  return this.getTitle()
194
254
  }
195
255
 
196
- , getPosition: function (inside) {
197
- return $.extend({}, (inside ? {top: 0, left: 0} : this.$element.offset()), {
198
- width: this.$element[0].offsetWidth
199
- , height: this.$element[0].offsetHeight
200
- })
256
+ , getPosition: function () {
257
+ var el = this.$element[0]
258
+ return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {
259
+ width: el.offsetWidth
260
+ , height: el.offsetHeight
261
+ }, this.$element.offset())
201
262
  }
202
263
 
203
264
  , getTitle: function () {
@@ -215,6 +276,10 @@
215
276
  return this.$tip = this.$tip || $(this.options.template)
216
277
  }
217
278
 
279
+ , arrow: function(){
280
+ return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow")
281
+ }
282
+
218
283
  , validate: function () {
219
284
  if (!this.$element[0].parentNode) {
220
285
  this.hide()
@@ -236,8 +301,8 @@
236
301
  }
237
302
 
238
303
  , toggle: function (e) {
239
- var self = $(e.currentTarget)[this.type](this._options).data(this.type)
240
- self[self.tip().hasClass('in') ? 'hide' : 'show']()
304
+ var self = e ? $(e.currentTarget)[this.type](this._options).data(this.type) : this
305
+ self.tip().hasClass('in') ? self.hide() : self.show()
241
306
  }
242
307
 
243
308
  , destroy: function () {
@@ -269,10 +334,11 @@
269
334
  , placement: 'top'
270
335
  , selector: false
271
336
  , template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>'
272
- , trigger: 'hover'
337
+ , trigger: 'hover focus'
273
338
  , title: ''
274
339
  , delay: 0
275
340
  , html: false
341
+ , container: false
276
342
  }
277
343
 
278
344
 
@@ -284,4 +350,4 @@
284
350
  return this
285
351
  }
286
352
 
287
- }(window.jQuery);
353
+ }(window.jQuery);