twitter-bootstrap-rails 2.2.1 → 2.2.3

Sign up to get free protection for your applications and to get access to all the features.

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);