entreprise7pro-bootstrap-sass 3.4.6

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 (171) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +19 -0
  4. data/CHANGELOG.md +233 -0
  5. data/CONTRIBUTING.md +86 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE +22 -0
  8. data/README.md +376 -0
  9. data/Rakefile +98 -0
  10. data/assets/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
  11. data/assets/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
  12. data/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
  13. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
  14. data/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
  15. data/assets/images/.keep +0 -0
  16. data/assets/javascripts/bootstrap/affix.js +166 -0
  17. data/assets/javascripts/bootstrap/alert.js +97 -0
  18. data/assets/javascripts/bootstrap/button.js +136 -0
  19. data/assets/javascripts/bootstrap/carousel.js +248 -0
  20. data/assets/javascripts/bootstrap/collapse.js +214 -0
  21. data/assets/javascripts/bootstrap/dropdown.js +167 -0
  22. data/assets/javascripts/bootstrap/modal.js +356 -0
  23. data/assets/javascripts/bootstrap/popover.js +123 -0
  24. data/assets/javascripts/bootstrap/scrollspy.js +174 -0
  25. data/assets/javascripts/bootstrap/tab.js +157 -0
  26. data/assets/javascripts/bootstrap/tooltip.js +679 -0
  27. data/assets/javascripts/bootstrap/transition.js +61 -0
  28. data/assets/javascripts/bootstrap-sprockets.js +12 -0
  29. data/assets/javascripts/bootstrap.js +2611 -0
  30. data/assets/javascripts/bootstrap.min.js +7 -0
  31. data/assets/javascripts/jquery.min.js +2 -0
  32. data/assets/stylesheets/_bootstrap-compass.scss +9 -0
  33. data/assets/stylesheets/_bootstrap-mincer.scss +19 -0
  34. data/assets/stylesheets/_bootstrap-sprockets.scss +9 -0
  35. data/assets/stylesheets/_bootstrap.scss +56 -0
  36. data/assets/stylesheets/bootstrap/_alerts.scss +73 -0
  37. data/assets/stylesheets/bootstrap/_badges.scss +68 -0
  38. data/assets/stylesheets/bootstrap/_breadcrumbs.scss +28 -0
  39. data/assets/stylesheets/bootstrap/_button-groups.scss +244 -0
  40. data/assets/stylesheets/bootstrap/_buttons.scss +168 -0
  41. data/assets/stylesheets/bootstrap/_carousel.scss +263 -0
  42. data/assets/stylesheets/bootstrap/_close.scss +37 -0
  43. data/assets/stylesheets/bootstrap/_code.scss +70 -0
  44. data/assets/stylesheets/bootstrap/_component-animations.scss +38 -0
  45. data/assets/stylesheets/bootstrap/_dropdowns.scss +212 -0
  46. data/assets/stylesheets/bootstrap/_forms.scss +602 -0
  47. data/assets/stylesheets/bootstrap/_glyphicons.scss +307 -0
  48. data/assets/stylesheets/bootstrap/_grid.scss +94 -0
  49. data/assets/stylesheets/bootstrap/_input-groups.scss +166 -0
  50. data/assets/stylesheets/bootstrap/_jumbotron.scss +55 -0
  51. data/assets/stylesheets/bootstrap/_labels.scss +66 -0
  52. data/assets/stylesheets/bootstrap/_list-group.scss +128 -0
  53. data/assets/stylesheets/bootstrap/_media.scss +66 -0
  54. data/assets/stylesheets/bootstrap/_mixins.scss +39 -0
  55. data/assets/stylesheets/bootstrap/_modals.scss +150 -0
  56. data/assets/stylesheets/bootstrap/_navbar.scss +657 -0
  57. data/assets/stylesheets/bootstrap/_navs.scss +242 -0
  58. data/assets/stylesheets/bootstrap/_normalize.scss +422 -0
  59. data/assets/stylesheets/bootstrap/_pager.scss +54 -0
  60. data/assets/stylesheets/bootstrap/_pagination.scss +86 -0
  61. data/assets/stylesheets/bootstrap/_panels.scss +271 -0
  62. data/assets/stylesheets/bootstrap/_popovers.scss +126 -0
  63. data/assets/stylesheets/bootstrap/_print.scss +99 -0
  64. data/assets/stylesheets/bootstrap/_progress-bars.scss +87 -0
  65. data/assets/stylesheets/bootstrap/_responsive-embed.scss +35 -0
  66. data/assets/stylesheets/bootstrap/_responsive-utilities.scss +157 -0
  67. data/assets/stylesheets/bootstrap/_scaffolding.scss +161 -0
  68. data/assets/stylesheets/bootstrap/_tables.scss +233 -0
  69. data/assets/stylesheets/bootstrap/_theme.scss +293 -0
  70. data/assets/stylesheets/bootstrap/_thumbnails.scss +38 -0
  71. data/assets/stylesheets/bootstrap/_tooltip.scss +112 -0
  72. data/assets/stylesheets/bootstrap/_type.scss +299 -0
  73. data/assets/stylesheets/bootstrap/_utilities.scss +55 -0
  74. data/assets/stylesheets/bootstrap/_variables.scss +875 -0
  75. data/assets/stylesheets/bootstrap/_wells.scss +29 -0
  76. data/assets/stylesheets/bootstrap/mixins/_alerts.scss +15 -0
  77. data/assets/stylesheets/bootstrap/mixins/_background-variant.scss +12 -0
  78. data/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
  79. data/assets/stylesheets/bootstrap/mixins/_buttons.scss +61 -0
  80. data/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
  81. data/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
  82. data/assets/stylesheets/bootstrap/mixins/_forms.scss +88 -0
  83. data/assets/stylesheets/bootstrap/mixins/_gradients.scss +50 -0
  84. data/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +82 -0
  85. data/assets/stylesheets/bootstrap/mixins/_grid.scss +123 -0
  86. data/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
  87. data/assets/stylesheets/bootstrap/mixins/_image.scss +28 -0
  88. data/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
  89. data/assets/stylesheets/bootstrap/mixins/_list-group.scss +32 -0
  90. data/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +11 -0
  91. data/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +10 -0
  92. data/assets/stylesheets/bootstrap/mixins/_opacity.scss +7 -0
  93. data/assets/stylesheets/bootstrap/mixins/_pagination.scss +24 -0
  94. data/assets/stylesheets/bootstrap/mixins/_panels.scss +24 -0
  95. data/assets/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
  96. data/assets/stylesheets/bootstrap/mixins/_reset-text.scss +18 -0
  97. data/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
  98. data/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +17 -0
  99. data/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
  100. data/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
  101. data/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
  102. data/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +12 -0
  103. data/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
  104. data/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +210 -0
  105. data/bower.json +38 -0
  106. data/composer.json +21 -0
  107. data/entreprise7pro-bootstrap-sass.gemspec +37 -0
  108. data/eyeglass-exports.js +7 -0
  109. data/lib/entreprise7pro-bootstrap-sass/engine.rb +17 -0
  110. data/lib/entreprise7pro-bootstrap-sass/version.rb +4 -0
  111. data/lib/entreprise7pro-bootstrap-sass.rb +91 -0
  112. data/package-lock.json +1011 -0
  113. data/package.json +48 -0
  114. data/sache.json +5 -0
  115. data/tasks/bower.rake +31 -0
  116. data/tasks/converter/char_string_scanner.rb +38 -0
  117. data/tasks/converter/fonts_conversion.rb +16 -0
  118. data/tasks/converter/js_conversion.rb +47 -0
  119. data/tasks/converter/less_conversion.rb +752 -0
  120. data/tasks/converter/logger.rb +57 -0
  121. data/tasks/converter/network.rb +97 -0
  122. data/tasks/converter.rb +80 -0
  123. data/templates/project/_bootstrap-variables.sass +876 -0
  124. data/templates/project/manifest.rb +20 -0
  125. data/templates/project/styles.sass +6 -0
  126. data/test/compilation_test.rb +30 -0
  127. data/test/dummy_node_mincer/apple-touch-icon-144-precomposed.png +0 -0
  128. data/test/dummy_node_mincer/application.css.ejs.scss +6 -0
  129. data/test/dummy_node_mincer/manifest.js +87 -0
  130. data/test/dummy_rails/README.rdoc +3 -0
  131. data/test/dummy_rails/Rakefile +6 -0
  132. data/test/dummy_rails/app/assets/images/.keep +0 -0
  133. data/test/dummy_rails/app/assets/javascripts/application.js +2 -0
  134. data/test/dummy_rails/app/assets/stylesheets/application.sass +2 -0
  135. data/test/dummy_rails/app/controllers/application_controller.rb +5 -0
  136. data/test/dummy_rails/app/controllers/pages_controller.rb +4 -0
  137. data/test/dummy_rails/app/helpers/application_helper.rb +2 -0
  138. data/test/dummy_rails/app/views/layouts/application.html.erb +14 -0
  139. data/test/dummy_rails/app/views/pages/root.html.slim +84 -0
  140. data/test/dummy_rails/config/application.rb +31 -0
  141. data/test/dummy_rails/config/boot.rb +5 -0
  142. data/test/dummy_rails/config/environment.rb +5 -0
  143. data/test/dummy_rails/config/environments/development.rb +23 -0
  144. data/test/dummy_rails/config/environments/production.rb +82 -0
  145. data/test/dummy_rails/config/environments/test.rb +38 -0
  146. data/test/dummy_rails/config/initializers/backtrace_silencers.rb +7 -0
  147. data/test/dummy_rails/config/initializers/filter_parameter_logging.rb +4 -0
  148. data/test/dummy_rails/config/initializers/inflections.rb +16 -0
  149. data/test/dummy_rails/config/initializers/mime_types.rb +5 -0
  150. data/test/dummy_rails/config/initializers/secret_token.rb +18 -0
  151. data/test/dummy_rails/config/initializers/session_store.rb +3 -0
  152. data/test/dummy_rails/config/initializers/wrap_parameters.rb +14 -0
  153. data/test/dummy_rails/config/locales/en.yml +3 -0
  154. data/test/dummy_rails/config/locales/es.yml +3 -0
  155. data/test/dummy_rails/config/routes.rb +3 -0
  156. data/test/dummy_rails/config.ru +4 -0
  157. data/test/dummy_rails/log/.keep +0 -0
  158. data/test/dummy_sass_only/Gemfile +4 -0
  159. data/test/dummy_sass_only/compile.rb +20 -0
  160. data/test/dummy_sass_only/import_all.scss +2 -0
  161. data/test/gemfiles/default.gemfile +3 -0
  162. data/test/node_mincer_test.rb +35 -0
  163. data/test/node_sass_compile_test.sh +9 -0
  164. data/test/pages_test.rb +14 -0
  165. data/test/sass_test.rb +29 -0
  166. data/test/sprockets_rails_test.rb +31 -0
  167. data/test/support/dummy_rails_integration.rb +22 -0
  168. data/test/support/reporting.rb +27 -0
  169. data/test/test_helper.rb +36 -0
  170. data/test/test_helper_rails.rb +6 -0
  171. metadata +467 -0
@@ -0,0 +1,679 @@
1
+ /* ========================================================================
2
+ * Bootstrap: tooltip.js v3.4.3
3
+ * https://bootstrap.7pro.ca/docs/3.4/javascript/#tooltip
4
+ * Inspired by the original jQuery.tipsy by Jason Frame
5
+ * ========================================================================
6
+ * Copyright 2024 Entreprise 7pro.ca Inc.
7
+ * Licensed under MIT (https://github.com/entreprise7pro/bootstrap/blob/v3-dev/LICENSE)
8
+ * Copyright 2011-2019 Twitter, Inc.
9
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/v3-dev/LICENSE)
10
+ * ======================================================================== */
11
+
12
+ +function ($) {
13
+ 'use strict';
14
+
15
+ var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
16
+
17
+ var uriAttrs = [
18
+ 'background',
19
+ 'cite',
20
+ 'href',
21
+ 'itemtype',
22
+ 'longdesc',
23
+ 'poster',
24
+ 'src',
25
+ 'xlink:href'
26
+ ]
27
+
28
+ var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
29
+
30
+ var DefaultWhitelist = {
31
+ // Global attributes allowed on any supplied element below.
32
+ '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
33
+ a: ['target', 'href', 'title', 'rel'],
34
+ area: [],
35
+ b: [],
36
+ br: [],
37
+ col: [],
38
+ code: [],
39
+ div: [],
40
+ em: [],
41
+ hr: [],
42
+ h1: [],
43
+ h2: [],
44
+ h3: [],
45
+ h4: [],
46
+ h5: [],
47
+ h6: [],
48
+ i: [],
49
+ img: ['src', 'alt', 'title', 'width', 'height'],
50
+ li: [],
51
+ ol: [],
52
+ p: [],
53
+ pre: [],
54
+ s: [],
55
+ small: [],
56
+ span: [],
57
+ sub: [],
58
+ sup: [],
59
+ strong: [],
60
+ u: [],
61
+ ul: []
62
+ }
63
+
64
+ /**
65
+ * A pattern that recognizes a commonly useful subset of URLs that are safe.
66
+ *
67
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
68
+ */
69
+ var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
70
+
71
+ /**
72
+ * A pattern that matches safe data URLs. Only matches image, video and audio types.
73
+ *
74
+ * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
75
+ */
76
+ var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i
77
+
78
+ function allowedAttribute(attr, allowedAttributeList) {
79
+ var attrName = attr.nodeName.toLowerCase()
80
+
81
+ if ($.inArray(attrName, allowedAttributeList) !== -1) {
82
+ if ($.inArray(attrName, uriAttrs) !== -1) {
83
+ return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
84
+ }
85
+
86
+ return true
87
+ }
88
+
89
+ var regExp = $(allowedAttributeList).filter(function (index, value) {
90
+ return value instanceof RegExp
91
+ })
92
+
93
+ // Check if a regular expression validates the attribute.
94
+ for (var i = 0, l = regExp.length; i < l; i++) {
95
+ if (attrName.match(regExp[i])) {
96
+ return true
97
+ }
98
+ }
99
+
100
+ return false
101
+ }
102
+
103
+ function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
104
+ if (unsafeHtml.length === 0) {
105
+ return unsafeHtml
106
+ }
107
+
108
+ if (sanitizeFn && typeof sanitizeFn === 'function') {
109
+ return sanitizeFn(unsafeHtml)
110
+ }
111
+
112
+ var createdDocument = document.implementation.createHTMLDocument('sanitization')
113
+ createdDocument.body.innerHTML = unsafeHtml
114
+
115
+ var whitelistKeys = $.map(whiteList, function (el, i) { return i })
116
+ var elements = $(createdDocument.body).find('*')
117
+
118
+ for (var i = 0, len = elements.length; i < len; i++) {
119
+ var el = elements[i]
120
+ var elName = el.nodeName.toLowerCase()
121
+
122
+ if ($.inArray(elName, whitelistKeys) === -1) {
123
+ el.parentNode.removeChild(el)
124
+
125
+ continue
126
+ }
127
+
128
+ var attributeList = $.map(el.attributes, function (el) { return el })
129
+ var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
130
+
131
+ for (var j = 0, len2 = attributeList.length; j < len2; j++) {
132
+ if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
133
+ el.removeAttribute(attributeList[j].nodeName)
134
+ }
135
+ }
136
+ }
137
+
138
+ return createdDocument.body.innerHTML
139
+ }
140
+
141
+ // TOOLTIP PUBLIC CLASS DEFINITION
142
+ // ===============================
143
+
144
+ var Tooltip = function (element, options) {
145
+ this.type = null
146
+ this.options = null
147
+ this.enabled = null
148
+ this.timeout = null
149
+ this.hoverState = null
150
+ this.$element = null
151
+ this.inState = null
152
+
153
+ this.init('tooltip', element, options)
154
+ }
155
+
156
+ Tooltip.VERSION = '3.4.3'
157
+
158
+ Tooltip.TRANSITION_DURATION = 150
159
+
160
+ Tooltip.DEFAULTS = {
161
+ animation: true,
162
+ placement: 'top',
163
+ selector: false,
164
+ template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
165
+ trigger: 'hover focus',
166
+ title: '',
167
+ delay: 0,
168
+ html: false,
169
+ container: false,
170
+ viewport: {
171
+ selector: 'body',
172
+ padding: 0
173
+ },
174
+ sanitize : true,
175
+ sanitizeFn : null,
176
+ whiteList : DefaultWhitelist
177
+ }
178
+
179
+ Tooltip.prototype.init = function (type, element, options) {
180
+ this.enabled = true
181
+ this.type = type
182
+ this.$element = $(element)
183
+ this.options = this.getOptions(options)
184
+ this.$viewport = this.options.viewport && $(document).find(
185
+ typeof this.options.viewport === 'function'
186
+ ? this.options.viewport.call(this, this.$element)
187
+ : (this.options.viewport.selector || this.options.viewport)
188
+ )
189
+ this.inState = { click: false, hover: false, focus: false }
190
+
191
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
192
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
193
+ }
194
+
195
+ var triggers = this.options.trigger.split(' ')
196
+
197
+ for (var i = triggers.length; i--;) {
198
+ var trigger = triggers[i]
199
+
200
+ if (trigger == 'click') {
201
+ this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
202
+ } else if (trigger != 'manual') {
203
+ var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin'
204
+ var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
205
+
206
+ this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
207
+ this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
208
+ }
209
+ }
210
+
211
+ this.options.selector ?
212
+ (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
213
+ this.fixTitle()
214
+ }
215
+
216
+ Tooltip.prototype.getDefaults = function () {
217
+ return Tooltip.DEFAULTS
218
+ }
219
+
220
+ Tooltip.prototype.getOptions = function (options) {
221
+ var dataAttributes = this.$element.data()
222
+
223
+
224
+ for (var dataAttr in dataAttributes) {
225
+ if (Object.prototype.hasOwnProperty.call(dataAttributes, dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
226
+ delete dataAttributes[dataAttr];
227
+ }
228
+ }
229
+
230
+ options = $.extend({}, this.getDefaults(), dataAttributes, options)
231
+
232
+ if (options.delay && typeof options.delay == 'number') {
233
+ options.delay = {
234
+ show: options.delay,
235
+ hide: options.delay
236
+ }
237
+ }
238
+
239
+ if (options.sanitize) {
240
+ options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
241
+ }
242
+
243
+ return options
244
+ }
245
+
246
+ Tooltip.prototype.getDelegateOptions = function () {
247
+ var options = {}
248
+ var defaults = this.getDefaults()
249
+
250
+ this._options && $.each(this._options, function (key, value) {
251
+ if (defaults[key] != value) options[key] = value
252
+ })
253
+
254
+ return options
255
+ }
256
+
257
+ Tooltip.prototype.enter = function (obj) {
258
+ var self = obj instanceof this.constructor ?
259
+ obj : $(obj.currentTarget).data('bs.' + this.type)
260
+
261
+ if (!self) {
262
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
263
+ $(obj.currentTarget).data('bs.' + this.type, self)
264
+ }
265
+
266
+ if (obj instanceof $.Event) {
267
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
268
+ }
269
+
270
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
271
+ self.hoverState = 'in'
272
+ return
273
+ }
274
+
275
+ clearTimeout(self.timeout)
276
+
277
+ self.hoverState = 'in'
278
+
279
+ if (!self.options.delay || !self.options.delay.show) return self.show()
280
+
281
+ self.timeout = setTimeout(function () {
282
+ if (self.hoverState == 'in') self.show()
283
+ }, self.options.delay.show)
284
+ }
285
+
286
+ Tooltip.prototype.isInStateTrue = function () {
287
+ for (var key in this.inState) {
288
+ if (this.inState[key]) return true
289
+ }
290
+
291
+ return false
292
+ }
293
+
294
+ Tooltip.prototype.leave = function (obj) {
295
+ var self = obj instanceof this.constructor ?
296
+ obj : $(obj.currentTarget).data('bs.' + this.type)
297
+
298
+ if (!self) {
299
+ self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
300
+ $(obj.currentTarget).data('bs.' + this.type, self)
301
+ }
302
+
303
+ if (obj instanceof $.Event) {
304
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
305
+ }
306
+
307
+ if (self.isInStateTrue()) return
308
+
309
+ clearTimeout(self.timeout)
310
+
311
+ self.hoverState = 'out'
312
+
313
+ if (!self.options.delay || !self.options.delay.hide) return self.hide()
314
+
315
+ self.timeout = setTimeout(function () {
316
+ if (self.hoverState == 'out') self.hide()
317
+ }, self.options.delay.hide)
318
+ }
319
+
320
+ Tooltip.prototype.show = function () {
321
+ var e = $.Event('show.bs.' + this.type)
322
+
323
+ if (this.hasContent() && this.enabled) {
324
+ this.$element.trigger(e)
325
+
326
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
327
+ if (e.isDefaultPrevented() || !inDom) return
328
+ var that = this
329
+
330
+ var $tip = this.tip()
331
+
332
+ var tipId = this.getUID(this.type)
333
+
334
+ this.setContent()
335
+ $tip.attr('id', tipId)
336
+ this.$element.attr('aria-describedby', tipId)
337
+
338
+ if (this.options.animation) $tip.addClass('fade')
339
+
340
+ var placement = typeof this.options.placement == 'function' ?
341
+ this.options.placement.call(this, $tip[0], this.$element[0]) :
342
+ this.options.placement
343
+
344
+ var autoToken = /\s?auto?\s?/i
345
+ var autoPlace = autoToken.test(placement)
346
+ if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
347
+
348
+ $tip
349
+ .detach()
350
+ .css({ top: 0, left: 0, display: 'block' })
351
+ .addClass(placement)
352
+ .data('bs.' + this.type, this)
353
+
354
+ this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
355
+ this.$element.trigger('inserted.bs.' + this.type)
356
+
357
+ var pos = this.getPosition()
358
+ var actualWidth = $tip[0].offsetWidth
359
+ var actualHeight = $tip[0].offsetHeight
360
+
361
+ if (autoPlace) {
362
+ var orgPlacement = placement
363
+ var viewportDim = this.getPosition(this.$viewport)
364
+
365
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
366
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
367
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
368
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
369
+ placement
370
+
371
+ $tip
372
+ .removeClass(orgPlacement)
373
+ .addClass(placement)
374
+ }
375
+
376
+ var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
377
+
378
+ this.applyPlacement(calculatedOffset, placement)
379
+
380
+ var complete = function () {
381
+ var prevHoverState = that.hoverState
382
+ that.$element.trigger('shown.bs.' + that.type)
383
+ that.hoverState = null
384
+
385
+ if (prevHoverState == 'out') that.leave(that)
386
+ }
387
+
388
+ $.support.transition && this.$tip.hasClass('fade') ?
389
+ $tip
390
+ .one('bsTransitionEnd', complete)
391
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
392
+ complete()
393
+ }
394
+ }
395
+
396
+ Tooltip.prototype.applyPlacement = function (offset, placement) {
397
+ var $tip = this.tip()
398
+ var width = $tip[0].offsetWidth
399
+ var height = $tip[0].offsetHeight
400
+
401
+ // manually read margins because getBoundingClientRect includes difference
402
+ var marginTop = parseInt($tip.css('margin-top'), 10)
403
+ var marginLeft = parseInt($tip.css('margin-left'), 10)
404
+
405
+ // we must check for NaN for ie 8/9
406
+ if (isNaN(marginTop)) marginTop = 0
407
+ if (isNaN(marginLeft)) marginLeft = 0
408
+
409
+ offset.top += marginTop
410
+ offset.left += marginLeft
411
+
412
+ // $.fn.offset doesn't round pixel values
413
+ // so we use setOffset directly with our own function B-0
414
+ $.offset.setOffset($tip[0], $.extend({
415
+ using: function (props) {
416
+ $tip.css({
417
+ top: Math.round(props.top),
418
+ left: Math.round(props.left)
419
+ })
420
+ }
421
+ }, offset), 0)
422
+
423
+ $tip.addClass('in')
424
+
425
+ // check to see if placing tip in new offset caused the tip to resize itself
426
+ var actualWidth = $tip[0].offsetWidth
427
+ var actualHeight = $tip[0].offsetHeight
428
+
429
+ if (placement == 'top' && actualHeight != height) {
430
+ offset.top = offset.top + height - actualHeight
431
+ }
432
+
433
+ var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
434
+
435
+ if (delta.left) offset.left += delta.left
436
+ else offset.top += delta.top
437
+
438
+ var isVertical = /top|bottom/.test(placement)
439
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
440
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
441
+
442
+ $tip.offset(offset)
443
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
444
+ }
445
+
446
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
447
+ this.arrow()
448
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
449
+ .css(isVertical ? 'top' : 'left', '')
450
+ }
451
+
452
+ Tooltip.prototype.setContent = function () {
453
+ var $tip = this.tip()
454
+ var title = this.getTitle()
455
+
456
+ if (this.options.html) {
457
+ if (this.options.sanitize) {
458
+ title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
459
+ }
460
+
461
+ $tip.find('.tooltip-inner').html(title)
462
+ } else {
463
+ $tip.find('.tooltip-inner').text(title)
464
+ }
465
+
466
+ $tip.removeClass('fade in top bottom left right')
467
+ }
468
+
469
+ Tooltip.prototype.hide = function (callback) {
470
+ var that = this
471
+ var $tip = $(this.$tip)
472
+ var e = $.Event('hide.bs.' + this.type)
473
+
474
+ function complete() {
475
+ if (that.hoverState != 'in') $tip.detach()
476
+ if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
477
+ that.$element
478
+ .removeAttr('aria-describedby')
479
+ .trigger('hidden.bs.' + that.type)
480
+ }
481
+ callback && callback()
482
+ }
483
+
484
+ this.$element.trigger(e)
485
+
486
+ if (e.isDefaultPrevented()) return
487
+
488
+ $tip.removeClass('in')
489
+
490
+ $.support.transition && $tip.hasClass('fade') ?
491
+ $tip
492
+ .one('bsTransitionEnd', complete)
493
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
494
+ complete()
495
+
496
+ this.hoverState = null
497
+
498
+ return this
499
+ }
500
+
501
+ Tooltip.prototype.fixTitle = function () {
502
+ var $e = this.$element
503
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
504
+ $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
505
+ }
506
+ }
507
+
508
+ Tooltip.prototype.hasContent = function () {
509
+ return this.getTitle()
510
+ }
511
+
512
+ Tooltip.prototype.getPosition = function ($element) {
513
+ $element = $element || this.$element
514
+
515
+ var el = $element[0]
516
+ var isBody = el.tagName == 'BODY'
517
+
518
+ var elRect = el.getBoundingClientRect()
519
+ if (elRect.width == null) {
520
+ // Width and height are missing in retro browsers, computing manually; see https://github.com/twbs/bootstrap/issues/14093.
521
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
522
+ }
523
+ var isSvg = window.SVGElement && el instanceof window.SVGElement
524
+ // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
525
+ // See https://github.com/twbs/bootstrap/issues/20280
526
+ var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
527
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
528
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
529
+
530
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
531
+ }
532
+
533
+ Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
534
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
535
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
536
+ placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
537
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
538
+
539
+ }
540
+
541
+ Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
542
+ var delta = { top: 0, left: 0 }
543
+ if (!this.$viewport) return delta
544
+
545
+ var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
546
+ var viewportDimensions = this.getPosition(this.$viewport)
547
+
548
+ if (/right|left/.test(placement)) {
549
+ var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
550
+ var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
551
+ if (topEdgeOffset < viewportDimensions.top) { // top overflow
552
+ delta.top = viewportDimensions.top - topEdgeOffset
553
+ } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
554
+ delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
555
+ }
556
+ } else {
557
+ var leftEdgeOffset = pos.left - viewportPadding
558
+ var rightEdgeOffset = pos.left + viewportPadding + actualWidth
559
+ if (leftEdgeOffset < viewportDimensions.left) { // left overflow
560
+ delta.left = viewportDimensions.left - leftEdgeOffset
561
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
562
+ delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
563
+ }
564
+ }
565
+
566
+ return delta
567
+ }
568
+
569
+ Tooltip.prototype.getTitle = function () {
570
+ var title
571
+ var $e = this.$element
572
+ var o = this.options
573
+
574
+ title = $e.attr('data-original-title')
575
+ || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)
576
+
577
+ return title
578
+ }
579
+
580
+ Tooltip.prototype.getUID = function (prefix) {
581
+ do prefix += ~~(Math.random() * 1000000)
582
+ while (document.getElementById(prefix))
583
+ return prefix
584
+ }
585
+
586
+ Tooltip.prototype.tip = function () {
587
+ if (!this.$tip) {
588
+ this.$tip = $(this.options.template)
589
+ if (this.$tip.length != 1) {
590
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
591
+ }
592
+ }
593
+ return this.$tip
594
+ }
595
+
596
+ Tooltip.prototype.arrow = function () {
597
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
598
+ }
599
+
600
+ Tooltip.prototype.enable = function () {
601
+ this.enabled = true
602
+ }
603
+
604
+ Tooltip.prototype.disable = function () {
605
+ this.enabled = false
606
+ }
607
+
608
+ Tooltip.prototype.toggleEnabled = function () {
609
+ this.enabled = !this.enabled
610
+ }
611
+
612
+ Tooltip.prototype.toggle = function (e) {
613
+ var self = this
614
+ if (e) {
615
+ self = $(e.currentTarget).data('bs.' + this.type)
616
+ if (!self) {
617
+ self = new this.constructor(e.currentTarget, this.getDelegateOptions())
618
+ $(e.currentTarget).data('bs.' + this.type, self)
619
+ }
620
+ }
621
+
622
+ if (e) {
623
+ self.inState.click = !self.inState.click
624
+ if (self.isInStateTrue()) self.enter(self)
625
+ else self.leave(self)
626
+ } else {
627
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
628
+ }
629
+ }
630
+
631
+ Tooltip.prototype.destroy = function () {
632
+ var that = this
633
+ clearTimeout(this.timeout)
634
+ this.hide(function () {
635
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
636
+ if (that.$tip) {
637
+ that.$tip.detach()
638
+ }
639
+ that.$tip = null
640
+ that.$arrow = null
641
+ that.$viewport = null
642
+ that.$element = null
643
+ })
644
+ }
645
+
646
+ Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
647
+ return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
648
+ }
649
+
650
+ // TOOLTIP PLUGIN DEFINITION
651
+ // =========================
652
+
653
+ function Plugin(option) {
654
+ return this.each(function () {
655
+ var $this = $(this)
656
+ var data = $this.data('bs.tooltip')
657
+ var options = typeof option == 'object' && option
658
+
659
+ if (!data && /destroy|hide/.test(option)) return
660
+ if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
661
+ if (typeof option == 'string') data[option]()
662
+ })
663
+ }
664
+
665
+ var old = $.fn.tooltip
666
+
667
+ $.fn.tooltip = Plugin
668
+ $.fn.tooltip.Constructor = Tooltip
669
+
670
+
671
+ // TOOLTIP NO CONFLICT
672
+ // ===================
673
+
674
+ $.fn.tooltip.noConflict = function () {
675
+ $.fn.tooltip = old
676
+ return this
677
+ }
678
+
679
+ }(jQuery);