padrino-admin 0.16.2 → 0.18.0
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.
- checksums.yaml +4 -4
- data/README.rdoc +3 -3
- data/Rakefile +0 -21
- data/lib/padrino-admin/access_control.rb +17 -4
- data/lib/padrino-admin/generators/actions.rb +1 -1
- data/lib/padrino-admin/generators/admin_app.rb +9 -11
- data/lib/padrino-admin/generators/admin_page.rb +12 -2
- data/lib/padrino-admin/generators/orm.rb +30 -47
- data/lib/padrino-admin/generators/templates/account/seeds.rb.tt +7 -2
- data/lib/padrino-admin/generators/templates/app/controllers/sessions.rb.tt +0 -4
- data/lib/padrino-admin/generators/templates/app.rb.tt +4 -1
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/affix.js +63 -36
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/alert.js +18 -11
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/bootstrap.min.js +4 -4
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/button.js +41 -23
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/carousel.js +90 -49
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/collapse.js +86 -44
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/dropdown.js +66 -48
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/modal.js +167 -52
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/popover.js +33 -20
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/scrollspy.js +58 -39
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/tab.js +55 -25
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/tooltip.js +370 -92
- data/lib/padrino-admin/generators/templates/assets/javascripts/bootstrap/transition.js +22 -11
- data/lib/padrino-admin/generators/templates/assets/javascripts/jquery-3.7.1.min.js +2 -0
- data/lib/padrino-admin/generators/templates/assets/stylesheets/application.css +14 -0
- data/lib/padrino-admin/generators/templates/assets/stylesheets/bootstrap.css +6 -4
- data/lib/padrino-admin/generators/templates/erb/app/base/index.erb.tt +1 -1
- data/lib/padrino-admin/generators/templates/erb/app/layouts/application.erb.tt +1 -1
- data/lib/padrino-admin/generators/templates/erb/app/sessions/new.erb.tt +1 -1
- data/lib/padrino-admin/generators/templates/erb/page/index.erb.tt +2 -2
- data/lib/padrino-admin/generators/templates/haml/app/base/index.haml.tt +1 -1
- data/lib/padrino-admin/generators/templates/haml/app/layouts/application.haml.tt +1 -1
- data/lib/padrino-admin/generators/templates/haml/app/sessions/new.haml.tt +1 -1
- data/lib/padrino-admin/generators/templates/slim/app/base/index.slim.tt +1 -1
- data/lib/padrino-admin/generators/templates/slim/app/layouts/application.slim.tt +1 -1
- data/lib/padrino-admin/generators/templates/slim/app/sessions/new.slim.tt +1 -1
- data/lib/padrino-admin/generators/templates/slim/page/index.slim.tt +2 -2
- data/lib/padrino-admin/helpers/authentication_helpers.rb +1 -1
- data/lib/padrino-admin/helpers/view_helpers.rb +3 -3
- data/lib/padrino-admin/locale/orm/pl.yml +0 -11
- data/lib/padrino-admin.rb +1 -1
- data/padrino-admin.gemspec +0 -2
- data/test/generators/test_account_model_generator.rb +1 -60
- data/test/generators/test_admin_app_generator.rb +159 -25
- data/test/generators/test_admin_page_generator.rb +110 -9
- data/test/test_admin_application.rb +123 -0
- metadata +9 -124
- data/lib/padrino-admin/bootstrap-less/alerts.less +0 -67
- data/lib/padrino-admin/bootstrap-less/badges.less +0 -55
- data/lib/padrino-admin/bootstrap-less/bootstrap.less +0 -49
- data/lib/padrino-admin/bootstrap-less/breadcrumbs.less +0 -26
- data/lib/padrino-admin/bootstrap-less/button-groups.less +0 -226
- data/lib/padrino-admin/bootstrap-less/buttons.less +0 -155
- data/lib/padrino-admin/bootstrap-less/carousel.less +0 -232
- data/lib/padrino-admin/bootstrap-less/close.less +0 -33
- data/lib/padrino-admin/bootstrap-less/code.less +0 -63
- data/lib/padrino-admin/bootstrap-less/component-animations.less +0 -29
- data/lib/padrino-admin/bootstrap-less/dropdowns.less +0 -213
- data/lib/padrino-admin/bootstrap-less/font-awesome/bordered-pulled.less +0 -16
- data/lib/padrino-admin/bootstrap-less/font-awesome/core.less +0 -12
- data/lib/padrino-admin/bootstrap-less/font-awesome/fixed-width.less +0 -6
- data/lib/padrino-admin/bootstrap-less/font-awesome/font-awesome.less +0 -17
- data/lib/padrino-admin/bootstrap-less/font-awesome/icons.less +0 -412
- data/lib/padrino-admin/bootstrap-less/font-awesome/larger.less +0 -13
- data/lib/padrino-admin/bootstrap-less/font-awesome/list.less +0 -19
- data/lib/padrino-admin/bootstrap-less/font-awesome/mixins.less +0 -20
- data/lib/padrino-admin/bootstrap-less/font-awesome/path.less +0 -14
- data/lib/padrino-admin/bootstrap-less/font-awesome/rotated-flipped.less +0 -9
- data/lib/padrino-admin/bootstrap-less/font-awesome/spinning.less +0 -30
- data/lib/padrino-admin/bootstrap-less/font-awesome/stacked.less +0 -20
- data/lib/padrino-admin/bootstrap-less/font-awesome/variables.less +0 -381
- data/lib/padrino-admin/bootstrap-less/forms.less +0 -419
- data/lib/padrino-admin/bootstrap-less/glyphicons.less +0 -233
- data/lib/padrino-admin/bootstrap-less/grid.less +0 -100
- data/lib/padrino-admin/bootstrap-less/input-groups.less +0 -157
- data/lib/padrino-admin/bootstrap-less/jumbotron.less +0 -44
- data/lib/padrino-admin/bootstrap-less/labels.less +0 -64
- data/lib/padrino-admin/bootstrap-less/list-group.less +0 -110
- data/lib/padrino-admin/bootstrap-less/media.less +0 -56
- data/lib/padrino-admin/bootstrap-less/mixins.less +0 -926
- data/lib/padrino-admin/bootstrap-less/modals.less +0 -138
- data/lib/padrino-admin/bootstrap-less/navbar.less +0 -616
- data/lib/padrino-admin/bootstrap-less/navs.less +0 -242
- data/lib/padrino-admin/bootstrap-less/normalize.less +0 -423
- data/lib/padrino-admin/bootstrap-less/padrino-admin.less +0 -18
- data/lib/padrino-admin/bootstrap-less/pager.less +0 -55
- data/lib/padrino-admin/bootstrap-less/pagination.less +0 -88
- data/lib/padrino-admin/bootstrap-less/panels.less +0 -230
- data/lib/padrino-admin/bootstrap-less/popovers.less +0 -133
- data/lib/padrino-admin/bootstrap-less/print.less +0 -101
- data/lib/padrino-admin/bootstrap-less/progress-bars.less +0 -80
- data/lib/padrino-admin/bootstrap-less/responsive-utilities.less +0 -93
- data/lib/padrino-admin/bootstrap-less/scaffolding.less +0 -134
- data/lib/padrino-admin/bootstrap-less/tables.less +0 -233
- data/lib/padrino-admin/bootstrap-less/theme.less +0 -247
- data/lib/padrino-admin/bootstrap-less/thumbnails.less +0 -36
- data/lib/padrino-admin/bootstrap-less/tooltip.less +0 -95
- data/lib/padrino-admin/bootstrap-less/type.less +0 -296
- data/lib/padrino-admin/bootstrap-less/utilities.less +0 -56
- data/lib/padrino-admin/bootstrap-less/variables.less +0 -827
- data/lib/padrino-admin/bootstrap-less/wells.less +0 -29
- data/lib/padrino-admin/generators/templates/account/couchrest.rb.tt +0 -67
- data/lib/padrino-admin/generators/templates/account/datamapper.rb.tt +0 -61
- data/lib/padrino-admin/generators/templates/account/dynamoid.rb.tt +0 -55
- data/lib/padrino-admin/generators/templates/account/minirecord.rb.tt +0 -44
- data/lib/padrino-admin/generators/templates/account/mongomapper.rb.tt +0 -47
- data/lib/padrino-admin/generators/templates/account/ohm.rb.tt +0 -70
- data/lib/padrino-admin/generators/templates/assets/javascripts/jquery-1.11.0.min.js +0 -4
- data/lib/padrino-admin/locale/orm/cs.yml +0 -12
- data/lib/padrino-admin/locale/orm/da.yml +0 -12
- data/lib/padrino-admin/locale/orm/de.yml +0 -12
- data/lib/padrino-admin/locale/orm/en.yml +0 -12
- data/lib/padrino-admin/locale/orm/es.yml +0 -12
- data/lib/padrino-admin/locale/orm/fr.yml +0 -12
- data/lib/padrino-admin/locale/orm/hu.yml +0 -12
- data/lib/padrino-admin/locale/orm/it.yml +0 -12
- data/lib/padrino-admin/locale/orm/ja.yml +0 -12
- data/lib/padrino-admin/locale/orm/lv.yml +0 -12
- data/lib/padrino-admin/locale/orm/nl.yml +0 -12
- data/lib/padrino-admin/locale/orm/no.yml +0 -12
- data/lib/padrino-admin/locale/orm/pt_br.yml +0 -12
- data/lib/padrino-admin/locale/orm/ro.yml +0 -12
- data/lib/padrino-admin/locale/orm/ru.yml +0 -12
- data/lib/padrino-admin/locale/orm/sv.yml +0 -12
- data/lib/padrino-admin/locale/orm/tr.yml +0 -12
- data/lib/padrino-admin/locale/orm/uk.yml +0 -12
- data/lib/padrino-admin/locale/orm/zh_cn.yml +0 -12
- data/lib/padrino-admin/locale/orm/zh_tw.yml +0 -12
|
@@ -1,47 +1,195 @@
|
|
|
1
1
|
/* ========================================================================
|
|
2
|
-
* Bootstrap: tooltip.js v3.1
|
|
3
|
-
*
|
|
2
|
+
* Bootstrap: tooltip.js v3.4.1
|
|
3
|
+
* https://getbootstrap.com/docs/3.4/javascript/#tooltip
|
|
4
4
|
* Inspired by the original jQuery.tipsy by Jason Frame
|
|
5
5
|
* ========================================================================
|
|
6
|
-
* Copyright 2011-
|
|
6
|
+
* Copyright 2011-2019 Twitter, Inc.
|
|
7
7
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
8
8
|
* ======================================================================== */
|
|
9
9
|
|
|
10
|
-
|
|
11
10
|
+function ($) {
|
|
12
11
|
'use strict';
|
|
13
12
|
|
|
13
|
+
var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']
|
|
14
|
+
|
|
15
|
+
var uriAttrs = [
|
|
16
|
+
'background',
|
|
17
|
+
'cite',
|
|
18
|
+
'href',
|
|
19
|
+
'itemtype',
|
|
20
|
+
'longdesc',
|
|
21
|
+
'poster',
|
|
22
|
+
'src',
|
|
23
|
+
'xlink:href'
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i
|
|
27
|
+
|
|
28
|
+
var DefaultWhitelist = {
|
|
29
|
+
// Global attributes allowed on any supplied element below.
|
|
30
|
+
'*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
|
|
31
|
+
a: ['target', 'href', 'title', 'rel'],
|
|
32
|
+
area: [],
|
|
33
|
+
b: [],
|
|
34
|
+
br: [],
|
|
35
|
+
col: [],
|
|
36
|
+
code: [],
|
|
37
|
+
div: [],
|
|
38
|
+
em: [],
|
|
39
|
+
hr: [],
|
|
40
|
+
h1: [],
|
|
41
|
+
h2: [],
|
|
42
|
+
h3: [],
|
|
43
|
+
h4: [],
|
|
44
|
+
h5: [],
|
|
45
|
+
h6: [],
|
|
46
|
+
i: [],
|
|
47
|
+
img: ['src', 'alt', 'title', 'width', 'height'],
|
|
48
|
+
li: [],
|
|
49
|
+
ol: [],
|
|
50
|
+
p: [],
|
|
51
|
+
pre: [],
|
|
52
|
+
s: [],
|
|
53
|
+
small: [],
|
|
54
|
+
span: [],
|
|
55
|
+
sub: [],
|
|
56
|
+
sup: [],
|
|
57
|
+
strong: [],
|
|
58
|
+
u: [],
|
|
59
|
+
ul: []
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A pattern that recognizes a commonly useful subset of URLs that are safe.
|
|
64
|
+
*
|
|
65
|
+
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
|
|
66
|
+
*/
|
|
67
|
+
var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* A pattern that matches safe data URLs. Only matches image, video and audio types.
|
|
71
|
+
*
|
|
72
|
+
* Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
|
|
73
|
+
*/
|
|
74
|
+
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
|
|
75
|
+
|
|
76
|
+
function allowedAttribute(attr, allowedAttributeList) {
|
|
77
|
+
var attrName = attr.nodeName.toLowerCase()
|
|
78
|
+
|
|
79
|
+
if ($.inArray(attrName, allowedAttributeList) !== -1) {
|
|
80
|
+
if ($.inArray(attrName, uriAttrs) !== -1) {
|
|
81
|
+
return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return true
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
var regExp = $(allowedAttributeList).filter(function (index, value) {
|
|
88
|
+
return value instanceof RegExp
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// Check if a regular expression validates the attribute.
|
|
92
|
+
for (var i = 0, l = regExp.length; i < l; i++) {
|
|
93
|
+
if (attrName.match(regExp[i])) {
|
|
94
|
+
return true
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return false
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
|
|
102
|
+
if (unsafeHtml.length === 0) {
|
|
103
|
+
return unsafeHtml
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (sanitizeFn && typeof sanitizeFn === 'function') {
|
|
107
|
+
return sanitizeFn(unsafeHtml)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// IE 8 and below don't support createHTMLDocument
|
|
111
|
+
if (!document.implementation || !document.implementation.createHTMLDocument) {
|
|
112
|
+
return unsafeHtml
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
var createdDocument = document.implementation.createHTMLDocument('sanitization')
|
|
116
|
+
createdDocument.body.innerHTML = unsafeHtml
|
|
117
|
+
|
|
118
|
+
var whitelistKeys = $.map(whiteList, function (el, i) { return i })
|
|
119
|
+
var elements = $(createdDocument.body).find('*')
|
|
120
|
+
|
|
121
|
+
for (var i = 0, len = elements.length; i < len; i++) {
|
|
122
|
+
var el = elements[i]
|
|
123
|
+
var elName = el.nodeName.toLowerCase()
|
|
124
|
+
|
|
125
|
+
if ($.inArray(elName, whitelistKeys) === -1) {
|
|
126
|
+
el.parentNode.removeChild(el)
|
|
127
|
+
|
|
128
|
+
continue
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
var attributeList = $.map(el.attributes, function (el) { return el })
|
|
132
|
+
var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])
|
|
133
|
+
|
|
134
|
+
for (var j = 0, len2 = attributeList.length; j < len2; j++) {
|
|
135
|
+
if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
|
|
136
|
+
el.removeAttribute(attributeList[j].nodeName)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return createdDocument.body.innerHTML
|
|
142
|
+
}
|
|
143
|
+
|
|
14
144
|
// TOOLTIP PUBLIC CLASS DEFINITION
|
|
15
145
|
// ===============================
|
|
16
146
|
|
|
17
147
|
var Tooltip = function (element, options) {
|
|
18
|
-
this.type =
|
|
19
|
-
this.options =
|
|
20
|
-
this.enabled =
|
|
21
|
-
this.timeout =
|
|
22
|
-
this.hoverState =
|
|
148
|
+
this.type = null
|
|
149
|
+
this.options = null
|
|
150
|
+
this.enabled = null
|
|
151
|
+
this.timeout = null
|
|
152
|
+
this.hoverState = null
|
|
23
153
|
this.$element = null
|
|
154
|
+
this.inState = null
|
|
24
155
|
|
|
25
156
|
this.init('tooltip', element, options)
|
|
26
157
|
}
|
|
27
158
|
|
|
159
|
+
Tooltip.VERSION = '3.4.1'
|
|
160
|
+
|
|
161
|
+
Tooltip.TRANSITION_DURATION = 150
|
|
162
|
+
|
|
28
163
|
Tooltip.DEFAULTS = {
|
|
29
164
|
animation: true,
|
|
30
165
|
placement: 'top',
|
|
31
166
|
selector: false,
|
|
32
|
-
template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
|
167
|
+
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
|
|
33
168
|
trigger: 'hover focus',
|
|
34
169
|
title: '',
|
|
35
170
|
delay: 0,
|
|
36
171
|
html: false,
|
|
37
|
-
container: false
|
|
172
|
+
container: false,
|
|
173
|
+
viewport: {
|
|
174
|
+
selector: 'body',
|
|
175
|
+
padding: 0
|
|
176
|
+
},
|
|
177
|
+
sanitize : true,
|
|
178
|
+
sanitizeFn : null,
|
|
179
|
+
whiteList : DefaultWhitelist
|
|
38
180
|
}
|
|
39
181
|
|
|
40
182
|
Tooltip.prototype.init = function (type, element, options) {
|
|
41
|
-
this.enabled
|
|
42
|
-
this.type
|
|
43
|
-
this.$element
|
|
44
|
-
this.options
|
|
183
|
+
this.enabled = true
|
|
184
|
+
this.type = type
|
|
185
|
+
this.$element = $(element)
|
|
186
|
+
this.options = this.getOptions(options)
|
|
187
|
+
this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
|
|
188
|
+
this.inState = { click: false, hover: false, focus: false }
|
|
189
|
+
|
|
190
|
+
if (this.$element[0] instanceof document.constructor && !this.options.selector) {
|
|
191
|
+
throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
|
|
192
|
+
}
|
|
45
193
|
|
|
46
194
|
var triggers = this.options.trigger.split(' ')
|
|
47
195
|
|
|
@@ -69,7 +217,15 @@
|
|
|
69
217
|
}
|
|
70
218
|
|
|
71
219
|
Tooltip.prototype.getOptions = function (options) {
|
|
72
|
-
|
|
220
|
+
var dataAttributes = this.$element.data()
|
|
221
|
+
|
|
222
|
+
for (var dataAttr in dataAttributes) {
|
|
223
|
+
if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
|
|
224
|
+
delete dataAttributes[dataAttr]
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
options = $.extend({}, this.getDefaults(), dataAttributes, options)
|
|
73
229
|
|
|
74
230
|
if (options.delay && typeof options.delay == 'number') {
|
|
75
231
|
options.delay = {
|
|
@@ -78,6 +234,10 @@
|
|
|
78
234
|
}
|
|
79
235
|
}
|
|
80
236
|
|
|
237
|
+
if (options.sanitize) {
|
|
238
|
+
options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
|
|
239
|
+
}
|
|
240
|
+
|
|
81
241
|
return options
|
|
82
242
|
}
|
|
83
243
|
|
|
@@ -94,7 +254,21 @@
|
|
|
94
254
|
|
|
95
255
|
Tooltip.prototype.enter = function (obj) {
|
|
96
256
|
var self = obj instanceof this.constructor ?
|
|
97
|
-
obj : $(obj.currentTarget)
|
|
257
|
+
obj : $(obj.currentTarget).data('bs.' + this.type)
|
|
258
|
+
|
|
259
|
+
if (!self) {
|
|
260
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
|
261
|
+
$(obj.currentTarget).data('bs.' + this.type, self)
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (obj instanceof $.Event) {
|
|
265
|
+
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
if (self.tip().hasClass('in') || self.hoverState == 'in') {
|
|
269
|
+
self.hoverState = 'in'
|
|
270
|
+
return
|
|
271
|
+
}
|
|
98
272
|
|
|
99
273
|
clearTimeout(self.timeout)
|
|
100
274
|
|
|
@@ -107,9 +281,28 @@
|
|
|
107
281
|
}, self.options.delay.show)
|
|
108
282
|
}
|
|
109
283
|
|
|
284
|
+
Tooltip.prototype.isInStateTrue = function () {
|
|
285
|
+
for (var key in this.inState) {
|
|
286
|
+
if (this.inState[key]) return true
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return false
|
|
290
|
+
}
|
|
291
|
+
|
|
110
292
|
Tooltip.prototype.leave = function (obj) {
|
|
111
293
|
var self = obj instanceof this.constructor ?
|
|
112
|
-
obj : $(obj.currentTarget)
|
|
294
|
+
obj : $(obj.currentTarget).data('bs.' + this.type)
|
|
295
|
+
|
|
296
|
+
if (!self) {
|
|
297
|
+
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
|
|
298
|
+
$(obj.currentTarget).data('bs.' + this.type, self)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (obj instanceof $.Event) {
|
|
302
|
+
self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (self.isInStateTrue()) return
|
|
113
306
|
|
|
114
307
|
clearTimeout(self.timeout)
|
|
115
308
|
|
|
@@ -128,12 +321,17 @@
|
|
|
128
321
|
if (this.hasContent() && this.enabled) {
|
|
129
322
|
this.$element.trigger(e)
|
|
130
323
|
|
|
131
|
-
|
|
132
|
-
|
|
324
|
+
var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
|
|
325
|
+
if (e.isDefaultPrevented() || !inDom) return
|
|
326
|
+
var that = this
|
|
133
327
|
|
|
134
328
|
var $tip = this.tip()
|
|
135
329
|
|
|
330
|
+
var tipId = this.getUID(this.type)
|
|
331
|
+
|
|
136
332
|
this.setContent()
|
|
333
|
+
$tip.attr('id', tipId)
|
|
334
|
+
this.$element.attr('aria-describedby', tipId)
|
|
137
335
|
|
|
138
336
|
if (this.options.animation) $tip.addClass('fade')
|
|
139
337
|
|
|
@@ -149,26 +347,23 @@
|
|
|
149
347
|
.detach()
|
|
150
348
|
.css({ top: 0, left: 0, display: 'block' })
|
|
151
349
|
.addClass(placement)
|
|
350
|
+
.data('bs.' + this.type, this)
|
|
152
351
|
|
|
153
|
-
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
|
|
352
|
+
this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
|
|
353
|
+
this.$element.trigger('inserted.bs.' + this.type)
|
|
154
354
|
|
|
155
355
|
var pos = this.getPosition()
|
|
156
356
|
var actualWidth = $tip[0].offsetWidth
|
|
157
357
|
var actualHeight = $tip[0].offsetHeight
|
|
158
358
|
|
|
159
359
|
if (autoPlace) {
|
|
160
|
-
var $parent = this.$element.parent()
|
|
161
|
-
|
|
162
360
|
var orgPlacement = placement
|
|
163
|
-
var
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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' :
|
|
361
|
+
var viewportDim = this.getPosition(this.$viewport)
|
|
362
|
+
|
|
363
|
+
placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
|
|
364
|
+
placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
|
|
365
|
+
placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
|
|
366
|
+
placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
|
|
172
367
|
placement
|
|
173
368
|
|
|
174
369
|
$tip
|
|
@@ -179,22 +374,24 @@
|
|
|
179
374
|
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
|
|
180
375
|
|
|
181
376
|
this.applyPlacement(calculatedOffset, placement)
|
|
182
|
-
this.hoverState = null
|
|
183
377
|
|
|
184
|
-
var complete = function() {
|
|
378
|
+
var complete = function () {
|
|
379
|
+
var prevHoverState = that.hoverState
|
|
185
380
|
that.$element.trigger('shown.bs.' + that.type)
|
|
381
|
+
that.hoverState = null
|
|
382
|
+
|
|
383
|
+
if (prevHoverState == 'out') that.leave(that)
|
|
186
384
|
}
|
|
187
385
|
|
|
188
386
|
$.support.transition && this.$tip.hasClass('fade') ?
|
|
189
387
|
$tip
|
|
190
|
-
.one(
|
|
191
|
-
.emulateTransitionEnd(
|
|
388
|
+
.one('bsTransitionEnd', complete)
|
|
389
|
+
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
|
192
390
|
complete()
|
|
193
391
|
}
|
|
194
392
|
}
|
|
195
393
|
|
|
196
394
|
Tooltip.prototype.applyPlacement = function (offset, placement) {
|
|
197
|
-
var replace
|
|
198
395
|
var $tip = this.tip()
|
|
199
396
|
var width = $tip[0].offsetWidth
|
|
200
397
|
var height = $tip[0].offsetHeight
|
|
@@ -207,8 +404,8 @@
|
|
|
207
404
|
if (isNaN(marginTop)) marginTop = 0
|
|
208
405
|
if (isNaN(marginLeft)) marginLeft = 0
|
|
209
406
|
|
|
210
|
-
offset.top
|
|
211
|
-
offset.left
|
|
407
|
+
offset.top += marginTop
|
|
408
|
+
offset.left += marginLeft
|
|
212
409
|
|
|
213
410
|
// $.fn.offset doesn't round pixel values
|
|
214
411
|
// so we use setOffset directly with our own function B-0
|
|
@@ -228,51 +425,58 @@
|
|
|
228
425
|
var actualHeight = $tip[0].offsetHeight
|
|
229
426
|
|
|
230
427
|
if (placement == 'top' && actualHeight != height) {
|
|
231
|
-
replace = true
|
|
232
428
|
offset.top = offset.top + height - actualHeight
|
|
233
429
|
}
|
|
234
430
|
|
|
235
|
-
|
|
236
|
-
var delta = 0
|
|
237
|
-
|
|
238
|
-
if (offset.left < 0) {
|
|
239
|
-
delta = offset.left * -2
|
|
240
|
-
offset.left = 0
|
|
241
|
-
|
|
242
|
-
$tip.offset(offset)
|
|
431
|
+
var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
|
|
243
432
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
433
|
+
if (delta.left) offset.left += delta.left
|
|
434
|
+
else offset.top += delta.top
|
|
247
435
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
}
|
|
436
|
+
var isVertical = /top|bottom/.test(placement)
|
|
437
|
+
var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
|
|
438
|
+
var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
|
|
252
439
|
|
|
253
|
-
|
|
440
|
+
$tip.offset(offset)
|
|
441
|
+
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
|
|
254
442
|
}
|
|
255
443
|
|
|
256
|
-
Tooltip.prototype.replaceArrow = function (delta, dimension,
|
|
257
|
-
this.arrow()
|
|
444
|
+
Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
|
|
445
|
+
this.arrow()
|
|
446
|
+
.css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
|
|
447
|
+
.css(isVertical ? 'top' : 'left', '')
|
|
258
448
|
}
|
|
259
449
|
|
|
260
450
|
Tooltip.prototype.setContent = function () {
|
|
261
451
|
var $tip = this.tip()
|
|
262
452
|
var title = this.getTitle()
|
|
263
453
|
|
|
264
|
-
|
|
454
|
+
if (this.options.html) {
|
|
455
|
+
if (this.options.sanitize) {
|
|
456
|
+
title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
$tip.find('.tooltip-inner').html(title)
|
|
460
|
+
} else {
|
|
461
|
+
$tip.find('.tooltip-inner').text(title)
|
|
462
|
+
}
|
|
463
|
+
|
|
265
464
|
$tip.removeClass('fade in top bottom left right')
|
|
266
465
|
}
|
|
267
466
|
|
|
268
|
-
Tooltip.prototype.hide = function () {
|
|
467
|
+
Tooltip.prototype.hide = function (callback) {
|
|
269
468
|
var that = this
|
|
270
|
-
var $tip = this
|
|
469
|
+
var $tip = $(this.$tip)
|
|
271
470
|
var e = $.Event('hide.bs.' + this.type)
|
|
272
471
|
|
|
273
472
|
function complete() {
|
|
274
473
|
if (that.hoverState != 'in') $tip.detach()
|
|
275
|
-
that.$element
|
|
474
|
+
if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
|
|
475
|
+
that.$element
|
|
476
|
+
.removeAttr('aria-describedby')
|
|
477
|
+
.trigger('hidden.bs.' + that.type)
|
|
478
|
+
}
|
|
479
|
+
callback && callback()
|
|
276
480
|
}
|
|
277
481
|
|
|
278
482
|
this.$element.trigger(e)
|
|
@@ -281,10 +485,10 @@
|
|
|
281
485
|
|
|
282
486
|
$tip.removeClass('in')
|
|
283
487
|
|
|
284
|
-
$.support.transition &&
|
|
488
|
+
$.support.transition && $tip.hasClass('fade') ?
|
|
285
489
|
$tip
|
|
286
|
-
.one(
|
|
287
|
-
.emulateTransitionEnd(
|
|
490
|
+
.one('bsTransitionEnd', complete)
|
|
491
|
+
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
|
|
288
492
|
complete()
|
|
289
493
|
|
|
290
494
|
this.hoverState = null
|
|
@@ -294,7 +498,7 @@
|
|
|
294
498
|
|
|
295
499
|
Tooltip.prototype.fixTitle = function () {
|
|
296
500
|
var $e = this.$element
|
|
297
|
-
if ($e.attr('title') || typeof
|
|
501
|
+
if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
|
|
298
502
|
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
|
|
299
503
|
}
|
|
300
504
|
}
|
|
@@ -303,19 +507,61 @@
|
|
|
303
507
|
return this.getTitle()
|
|
304
508
|
}
|
|
305
509
|
|
|
306
|
-
Tooltip.prototype.getPosition = function () {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
510
|
+
Tooltip.prototype.getPosition = function ($element) {
|
|
511
|
+
$element = $element || this.$element
|
|
512
|
+
|
|
513
|
+
var el = $element[0]
|
|
514
|
+
var isBody = el.tagName == 'BODY'
|
|
515
|
+
|
|
516
|
+
var elRect = el.getBoundingClientRect()
|
|
517
|
+
if (elRect.width == null) {
|
|
518
|
+
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
|
|
519
|
+
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
|
|
520
|
+
}
|
|
521
|
+
var isSvg = window.SVGElement && el instanceof window.SVGElement
|
|
522
|
+
// Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
|
|
523
|
+
// See https://github.com/twbs/bootstrap/issues/20280
|
|
524
|
+
var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
|
|
525
|
+
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
|
|
526
|
+
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
|
|
527
|
+
|
|
528
|
+
return $.extend({}, elRect, scroll, outerDims, elOffset)
|
|
312
529
|
}
|
|
313
530
|
|
|
314
531
|
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
|
|
532
|
+
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
|
533
|
+
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
|
|
317
534
|
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
|
|
535
|
+
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
|
|
536
|
+
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
|
|
540
|
+
var delta = { top: 0, left: 0 }
|
|
541
|
+
if (!this.$viewport) return delta
|
|
542
|
+
|
|
543
|
+
var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
|
|
544
|
+
var viewportDimensions = this.getPosition(this.$viewport)
|
|
545
|
+
|
|
546
|
+
if (/right|left/.test(placement)) {
|
|
547
|
+
var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll
|
|
548
|
+
var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
|
|
549
|
+
if (topEdgeOffset < viewportDimensions.top) { // top overflow
|
|
550
|
+
delta.top = viewportDimensions.top - topEdgeOffset
|
|
551
|
+
} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
|
|
552
|
+
delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
var leftEdgeOffset = pos.left - viewportPadding
|
|
556
|
+
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
|
|
557
|
+
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
|
|
558
|
+
delta.left = viewportDimensions.left - leftEdgeOffset
|
|
559
|
+
} else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
|
|
560
|
+
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return delta
|
|
319
565
|
}
|
|
320
566
|
|
|
321
567
|
Tooltip.prototype.getTitle = function () {
|
|
@@ -329,20 +575,24 @@
|
|
|
329
575
|
return title
|
|
330
576
|
}
|
|
331
577
|
|
|
332
|
-
Tooltip.prototype.
|
|
333
|
-
|
|
578
|
+
Tooltip.prototype.getUID = function (prefix) {
|
|
579
|
+
do prefix += ~~(Math.random() * 1000000)
|
|
580
|
+
while (document.getElementById(prefix))
|
|
581
|
+
return prefix
|
|
334
582
|
}
|
|
335
583
|
|
|
336
|
-
Tooltip.prototype.
|
|
337
|
-
|
|
584
|
+
Tooltip.prototype.tip = function () {
|
|
585
|
+
if (!this.$tip) {
|
|
586
|
+
this.$tip = $(this.options.template)
|
|
587
|
+
if (this.$tip.length != 1) {
|
|
588
|
+
throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
return this.$tip
|
|
338
592
|
}
|
|
339
593
|
|
|
340
|
-
Tooltip.prototype.
|
|
341
|
-
|
|
342
|
-
this.hide()
|
|
343
|
-
this.$element = null
|
|
344
|
-
this.options = null
|
|
345
|
-
}
|
|
594
|
+
Tooltip.prototype.arrow = function () {
|
|
595
|
+
return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
|
|
346
596
|
}
|
|
347
597
|
|
|
348
598
|
Tooltip.prototype.enable = function () {
|
|
@@ -358,33 +608,61 @@
|
|
|
358
608
|
}
|
|
359
609
|
|
|
360
610
|
Tooltip.prototype.toggle = function (e) {
|
|
361
|
-
var self =
|
|
362
|
-
|
|
611
|
+
var self = this
|
|
612
|
+
if (e) {
|
|
613
|
+
self = $(e.currentTarget).data('bs.' + this.type)
|
|
614
|
+
if (!self) {
|
|
615
|
+
self = new this.constructor(e.currentTarget, this.getDelegateOptions())
|
|
616
|
+
$(e.currentTarget).data('bs.' + this.type, self)
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (e) {
|
|
621
|
+
self.inState.click = !self.inState.click
|
|
622
|
+
if (self.isInStateTrue()) self.enter(self)
|
|
623
|
+
else self.leave(self)
|
|
624
|
+
} else {
|
|
625
|
+
self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
|
|
626
|
+
}
|
|
363
627
|
}
|
|
364
628
|
|
|
365
629
|
Tooltip.prototype.destroy = function () {
|
|
630
|
+
var that = this
|
|
366
631
|
clearTimeout(this.timeout)
|
|
367
|
-
this.hide(
|
|
632
|
+
this.hide(function () {
|
|
633
|
+
that.$element.off('.' + that.type).removeData('bs.' + that.type)
|
|
634
|
+
if (that.$tip) {
|
|
635
|
+
that.$tip.detach()
|
|
636
|
+
}
|
|
637
|
+
that.$tip = null
|
|
638
|
+
that.$arrow = null
|
|
639
|
+
that.$viewport = null
|
|
640
|
+
that.$element = null
|
|
641
|
+
})
|
|
368
642
|
}
|
|
369
643
|
|
|
644
|
+
Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
|
|
645
|
+
return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
|
|
646
|
+
}
|
|
370
647
|
|
|
371
648
|
// TOOLTIP PLUGIN DEFINITION
|
|
372
649
|
// =========================
|
|
373
650
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
$.fn.tooltip = function (option) {
|
|
651
|
+
function Plugin(option) {
|
|
377
652
|
return this.each(function () {
|
|
378
653
|
var $this = $(this)
|
|
379
654
|
var data = $this.data('bs.tooltip')
|
|
380
655
|
var options = typeof option == 'object' && option
|
|
381
656
|
|
|
382
|
-
if (!data && option
|
|
657
|
+
if (!data && /destroy|hide/.test(option)) return
|
|
383
658
|
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
|
|
384
659
|
if (typeof option == 'string') data[option]()
|
|
385
660
|
})
|
|
386
661
|
}
|
|
387
662
|
|
|
663
|
+
var old = $.fn.tooltip
|
|
664
|
+
|
|
665
|
+
$.fn.tooltip = Plugin
|
|
388
666
|
$.fn.tooltip.Constructor = Tooltip
|
|
389
667
|
|
|
390
668
|
|