@openeuropa/bcl-bootstrap 0.25.1 → 0.26.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.
- package/bootstrap-icons.svg +1 -1
- package/icons/apple.svg +2 -2
- package/icons/boombox-fill.svg +2 -2
- package/icons/cup-fill.svg +1 -1
- package/icons/cup.svg +1 -1
- package/js/dist/alert.js +3 -12
- package/js/dist/alert.js.map +1 -1
- package/js/dist/base-component.js +32 -18
- package/js/dist/base-component.js.map +1 -1
- package/js/dist/button.js +3 -12
- package/js/dist/button.js.map +1 -1
- package/js/dist/carousel.js +207 -307
- package/js/dist/carousel.js.map +1 -1
- package/js/dist/collapse.js +57 -88
- package/js/dist/collapse.js.map +1 -1
- package/js/dist/dom/data.js +1 -3
- package/js/dist/dom/data.js.map +1 -1
- package/js/dist/dom/event-handler.js +87 -106
- package/js/dist/dom/event-handler.js.map +1 -1
- package/js/dist/dom/manipulator.js +21 -25
- package/js/dist/dom/manipulator.js.map +1 -1
- package/js/dist/dom/selector-engine.js +11 -10
- package/js/dist/dom/selector-engine.js.map +1 -1
- package/js/dist/dropdown.js +83 -115
- package/js/dist/dropdown.js.map +1 -1
- package/js/dist/modal.js +95 -152
- package/js/dist/modal.js.map +1 -1
- package/js/dist/offcanvas.js +75 -58
- package/js/dist/offcanvas.js.map +1 -1
- package/js/dist/popover.js +29 -56
- package/js/dist/popover.js.map +1 -1
- package/js/dist/scrollspy.js +176 -125
- package/js/dist/scrollspy.js.map +1 -1
- package/js/dist/tab.js +207 -92
- package/js/dist/tab.js.map +1 -1
- package/js/dist/toast.js +23 -37
- package/js/dist/toast.js.map +1 -1
- package/js/dist/tooltip.js +259 -348
- package/js/dist/tooltip.js.map +1 -1
- package/js/dist/util/backdrop.js +62 -39
- package/js/dist/util/backdrop.js.map +1 -1
- package/js/dist/util/component-functions.js +1 -1
- package/js/dist/util/component-functions.js.map +1 -1
- package/js/dist/util/config.js +75 -0
- package/js/dist/util/config.js.map +1 -0
- package/js/dist/util/focustrap.js +41 -34
- package/js/dist/util/focustrap.js.map +1 -1
- package/js/dist/util/index.js +56 -52
- package/js/dist/util/index.js.map +1 -1
- package/js/dist/util/sanitizer.js +12 -19
- package/js/dist/util/sanitizer.js.map +1 -1
- package/js/dist/util/scrollbar.js +49 -34
- package/js/dist/util/scrollbar.js.map +1 -1
- package/js/dist/util/swipe.js +151 -0
- package/js/dist/util/swipe.js.map +1 -0
- package/js/dist/util/template-factory.js +173 -0
- package/js/dist/util/template-factory.js.map +1 -0
- package/js/src/alert.js +3 -15
- package/js/src/base-component.js +28 -18
- package/js/src/button.js +3 -17
- package/js/src/carousel.js +203 -319
- package/js/src/collapse.js +61 -94
- package/js/src/dom/data.js +1 -3
- package/js/src/dom/event-handler.js +80 -108
- package/js/src/dom/manipulator.js +22 -31
- package/js/src/dom/selector-engine.js +10 -19
- package/js/src/dropdown.js +84 -138
- package/js/src/modal.js +94 -158
- package/js/src/offcanvas.js +72 -61
- package/js/src/popover.js +31 -62
- package/js/src/scrollspy.js +166 -171
- package/js/src/tab.js +193 -110
- package/js/src/toast.js +19 -41
- package/js/src/tooltip.js +259 -371
- package/js/src/util/backdrop.js +55 -36
- package/js/src/util/component-functions.js +1 -1
- package/js/src/util/config.js +66 -0
- package/js/src/util/focustrap.js +38 -28
- package/js/src/util/index.js +67 -64
- package/js/src/util/sanitizer.js +11 -19
- package/js/src/util/scrollbar.js +47 -30
- package/js/src/util/swipe.js +146 -0
- package/js/src/util/template-factory.js +160 -0
- package/package.json +4 -4
- package/scss/_accordion.scss +52 -24
- package/scss/_alert.scss +18 -4
- package/scss/_badge.scss +14 -5
- package/scss/_breadcrumb.scss +22 -10
- package/scss/_button-group.scss +3 -0
- package/scss/_buttons.scss +97 -22
- package/scss/_card.scss +55 -37
- package/scss/_close.scss +1 -1
- package/scss/_containers.scss +1 -1
- package/scss/_dropdown.scss +83 -75
- package/scss/_functions.scss +7 -7
- package/scss/_grid.scss +3 -3
- package/scss/_helpers.scss +1 -0
- package/scss/_list-group.scss +44 -27
- package/scss/_maps.scss +54 -0
- package/scss/_modal.scss +71 -43
- package/scss/_nav.scss +53 -20
- package/scss/_navbar.scss +91 -150
- package/scss/_offcanvas.scss +119 -59
- package/scss/_pagination.scss +66 -21
- package/scss/_placeholders.scss +1 -1
- package/scss/_popover.scss +90 -52
- package/scss/_progress.scss +20 -9
- package/scss/_reboot.scss +25 -40
- package/scss/_root.scss +40 -21
- package/scss/_spinners.scss +38 -22
- package/scss/_tables.scss +32 -23
- package/scss/_toasts.scss +35 -16
- package/scss/_tooltip.scss +61 -56
- package/scss/_type.scss +2 -0
- package/scss/_utilities.scss +43 -26
- package/scss/_variables.scss +113 -121
- package/scss/bootstrap-grid.scss +3 -6
- package/scss/bootstrap-reboot.scss +3 -7
- package/scss/bootstrap-utilities.scss +3 -6
- package/scss/bootstrap.scss +4 -6
- package/scss/forms/_floating-labels.scss +14 -3
- package/scss/forms/_form-check.scss +28 -5
- package/scss/forms/_form-control.scss +12 -37
- package/scss/forms/_form-select.scss +0 -1
- package/scss/forms/_input-group.scss +15 -7
- package/scss/helpers/_color-bg.scss +10 -0
- package/scss/helpers/_colored-links.scss +2 -2
- package/scss/helpers/_position.scss +7 -1
- package/scss/helpers/_ratio.scss +2 -2
- package/scss/helpers/_vr.scss +1 -1
- package/scss/mixins/_alert.scss +7 -3
- package/scss/mixins/_banner.scss +9 -0
- package/scss/mixins/_breakpoints.scss +8 -8
- package/scss/mixins/_buttons.scss +32 -95
- package/scss/mixins/_container.scss +4 -2
- package/scss/mixins/_forms.scss +8 -0
- package/scss/mixins/_gradients.scss +1 -1
- package/scss/mixins/_grid.scss +12 -12
- package/scss/mixins/_pagination.scss +4 -25
- package/scss/mixins/_reset-text.scss +1 -1
- package/scss/mixins/_table-variants.scss +12 -9
- package/scss/mixins/_utilities.scss +12 -4
package/js/src/scrollspy.js
CHANGED
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* --------------------------------------------------------------------------
|
|
3
|
-
* Bootstrap (v5.
|
|
3
|
+
* Bootstrap (v5.2.0): scrollspy.js
|
|
4
4
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
5
5
|
* --------------------------------------------------------------------------
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
defineJQueryPlugin,
|
|
10
|
-
getElement,
|
|
11
|
-
getSelectorFromElement,
|
|
12
|
-
typeCheckConfig
|
|
13
|
-
} from './util/index'
|
|
8
|
+
import { defineJQueryPlugin, getElement, isDisabled, isVisible } from './util/index'
|
|
14
9
|
import EventHandler from './dom/event-handler'
|
|
15
|
-
import Manipulator from './dom/manipulator'
|
|
16
10
|
import SelectorEngine from './dom/selector-engine'
|
|
17
11
|
import BaseComponent from './base-component'
|
|
18
12
|
|
|
19
13
|
/**
|
|
20
|
-
* ------------------------------------------------------------------------
|
|
21
14
|
* Constants
|
|
22
|
-
* ------------------------------------------------------------------------
|
|
23
15
|
*/
|
|
24
16
|
|
|
25
17
|
const NAME = 'scrollspy'
|
|
@@ -27,234 +19,241 @@ const DATA_KEY = 'bs.scrollspy'
|
|
|
27
19
|
const EVENT_KEY = `.${DATA_KEY}`
|
|
28
20
|
const DATA_API_KEY = '.data-api'
|
|
29
21
|
|
|
30
|
-
const Default = {
|
|
31
|
-
offset: 10,
|
|
32
|
-
method: 'auto',
|
|
33
|
-
target: ''
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const DefaultType = {
|
|
37
|
-
offset: 'number',
|
|
38
|
-
method: 'string',
|
|
39
|
-
target: '(string|element)'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
22
|
const EVENT_ACTIVATE = `activate${EVENT_KEY}`
|
|
43
|
-
const
|
|
23
|
+
const EVENT_CLICK = `click${EVENT_KEY}`
|
|
44
24
|
const EVENT_LOAD_DATA_API = `load${EVENT_KEY}${DATA_API_KEY}`
|
|
45
25
|
|
|
46
26
|
const CLASS_NAME_DROPDOWN_ITEM = 'dropdown-item'
|
|
47
27
|
const CLASS_NAME_ACTIVE = 'active'
|
|
48
28
|
|
|
49
29
|
const SELECTOR_DATA_SPY = '[data-bs-spy="scroll"]'
|
|
30
|
+
const SELECTOR_TARGET_LINKS = '[href]'
|
|
50
31
|
const SELECTOR_NAV_LIST_GROUP = '.nav, .list-group'
|
|
51
32
|
const SELECTOR_NAV_LINKS = '.nav-link'
|
|
52
33
|
const SELECTOR_NAV_ITEMS = '.nav-item'
|
|
53
34
|
const SELECTOR_LIST_ITEMS = '.list-group-item'
|
|
54
|
-
const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${
|
|
35
|
+
const SELECTOR_LINK_ITEMS = `${SELECTOR_NAV_LINKS}, ${SELECTOR_NAV_ITEMS} > ${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`
|
|
55
36
|
const SELECTOR_DROPDOWN = '.dropdown'
|
|
56
37
|
const SELECTOR_DROPDOWN_TOGGLE = '.dropdown-toggle'
|
|
57
38
|
|
|
58
|
-
const
|
|
59
|
-
|
|
39
|
+
const Default = {
|
|
40
|
+
offset: null, // TODO: v6 @deprecated, keep it for backwards compatibility reasons
|
|
41
|
+
rootMargin: '0px 0px -25%',
|
|
42
|
+
smoothScroll: false,
|
|
43
|
+
target: null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const DefaultType = {
|
|
47
|
+
offset: '(number|null)', // TODO v6 @deprecated, keep it for backwards compatibility reasons
|
|
48
|
+
rootMargin: 'string',
|
|
49
|
+
smoothScroll: 'boolean',
|
|
50
|
+
target: 'element'
|
|
51
|
+
}
|
|
60
52
|
|
|
61
53
|
/**
|
|
62
|
-
*
|
|
63
|
-
* Class Definition
|
|
64
|
-
* ------------------------------------------------------------------------
|
|
54
|
+
* Class definition
|
|
65
55
|
*/
|
|
66
56
|
|
|
67
57
|
class ScrollSpy extends BaseComponent {
|
|
68
58
|
constructor(element, config) {
|
|
69
|
-
super(element)
|
|
70
|
-
this._scrollElement = this._element.tagName === 'BODY' ? window : this._element
|
|
71
|
-
this._config = this._getConfig(config)
|
|
72
|
-
this._offsets = []
|
|
73
|
-
this._targets = []
|
|
74
|
-
this._activeTarget = null
|
|
75
|
-
this._scrollHeight = 0
|
|
76
|
-
|
|
77
|
-
EventHandler.on(this._scrollElement, EVENT_SCROLL, () => this._process())
|
|
59
|
+
super(element, config)
|
|
78
60
|
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
61
|
+
// this._element is the observablesContainer and config.target the menu links wrapper
|
|
62
|
+
this._targetLinks = new Map()
|
|
63
|
+
this._observableSections = new Map()
|
|
64
|
+
this._rootElement = getComputedStyle(this._element).overflowY === 'visible' ? null : this._element
|
|
65
|
+
this._activeTarget = null
|
|
66
|
+
this._observer = null
|
|
67
|
+
this._previousScrollData = {
|
|
68
|
+
visibleEntryTop: 0,
|
|
69
|
+
parentScrollTop: 0
|
|
70
|
+
}
|
|
71
|
+
this.refresh() // initialize
|
|
81
72
|
}
|
|
82
73
|
|
|
83
74
|
// Getters
|
|
84
|
-
|
|
85
75
|
static get Default() {
|
|
86
76
|
return Default
|
|
87
77
|
}
|
|
88
78
|
|
|
79
|
+
static get DefaultType() {
|
|
80
|
+
return DefaultType
|
|
81
|
+
}
|
|
82
|
+
|
|
89
83
|
static get NAME() {
|
|
90
84
|
return NAME
|
|
91
85
|
}
|
|
92
86
|
|
|
93
87
|
// Public
|
|
94
|
-
|
|
95
88
|
refresh() {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
METHOD_POSITION
|
|
99
|
-
|
|
100
|
-
const offsetMethod = this._config.method === 'auto' ?
|
|
101
|
-
autoMethod :
|
|
102
|
-
this._config.method
|
|
103
|
-
|
|
104
|
-
const offsetBase = offsetMethod === METHOD_POSITION ?
|
|
105
|
-
this._getScrollTop() :
|
|
106
|
-
0
|
|
107
|
-
|
|
108
|
-
this._offsets = []
|
|
109
|
-
this._targets = []
|
|
110
|
-
this._scrollHeight = this._getScrollHeight()
|
|
111
|
-
|
|
112
|
-
const targets = SelectorEngine.find(SELECTOR_LINK_ITEMS, this._config.target)
|
|
113
|
-
|
|
114
|
-
targets.map(element => {
|
|
115
|
-
const targetSelector = getSelectorFromElement(element)
|
|
116
|
-
const target = targetSelector ? SelectorEngine.findOne(targetSelector) : null
|
|
117
|
-
|
|
118
|
-
if (target) {
|
|
119
|
-
const targetBCR = target.getBoundingClientRect()
|
|
120
|
-
if (targetBCR.width || targetBCR.height) {
|
|
121
|
-
return [
|
|
122
|
-
Manipulator[offsetMethod](target).top + offsetBase,
|
|
123
|
-
targetSelector
|
|
124
|
-
]
|
|
125
|
-
}
|
|
126
|
-
}
|
|
89
|
+
this._initializeTargetsAndObservables()
|
|
90
|
+
this._maybeEnableSmoothScroll()
|
|
127
91
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
.
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
92
|
+
if (this._observer) {
|
|
93
|
+
this._observer.disconnect()
|
|
94
|
+
} else {
|
|
95
|
+
this._observer = this._getNewObserver()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
for (const section of this._observableSections.values()) {
|
|
99
|
+
this._observer.observe(section)
|
|
100
|
+
}
|
|
136
101
|
}
|
|
137
102
|
|
|
138
103
|
dispose() {
|
|
139
|
-
|
|
104
|
+
this._observer.disconnect()
|
|
140
105
|
super.dispose()
|
|
141
106
|
}
|
|
142
107
|
|
|
143
108
|
// Private
|
|
109
|
+
_configAfterMerge(config) {
|
|
110
|
+
// TODO: on v6 target should be given explicitly & remove the {target: 'ss-target'} case
|
|
111
|
+
config.target = getElement(config.target) || document.body
|
|
144
112
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
...Default,
|
|
148
|
-
...Manipulator.getDataAttributes(this._element),
|
|
149
|
-
...(typeof config === 'object' && config ? config : {})
|
|
150
|
-
}
|
|
113
|
+
return config
|
|
114
|
+
}
|
|
151
115
|
|
|
152
|
-
|
|
116
|
+
_maybeEnableSmoothScroll() {
|
|
117
|
+
if (!this._config.smoothScroll) {
|
|
118
|
+
return
|
|
119
|
+
}
|
|
153
120
|
|
|
154
|
-
|
|
121
|
+
// unregister any previous listeners
|
|
122
|
+
EventHandler.off(this._config.target, EVENT_CLICK)
|
|
123
|
+
|
|
124
|
+
EventHandler.on(this._config.target, EVENT_CLICK, SELECTOR_TARGET_LINKS, event => {
|
|
125
|
+
const observableSection = this._observableSections.get(event.target.hash)
|
|
126
|
+
if (observableSection) {
|
|
127
|
+
event.preventDefault()
|
|
128
|
+
const root = this._rootElement || window
|
|
129
|
+
const height = observableSection.offsetTop - this._element.offsetTop
|
|
130
|
+
if (root.scrollTo) {
|
|
131
|
+
root.scrollTo({ top: height, behavior: 'smooth' })
|
|
132
|
+
return
|
|
133
|
+
}
|
|
155
134
|
|
|
156
|
-
|
|
135
|
+
// Chrome 60 doesn't support `scrollTo`
|
|
136
|
+
root.scrollTop = height
|
|
137
|
+
}
|
|
138
|
+
})
|
|
157
139
|
}
|
|
158
140
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
this.
|
|
162
|
-
|
|
163
|
-
|
|
141
|
+
_getNewObserver() {
|
|
142
|
+
const options = {
|
|
143
|
+
root: this._rootElement,
|
|
144
|
+
threshold: [0.1, 0.5, 1],
|
|
145
|
+
rootMargin: this._getRootMargin()
|
|
146
|
+
}
|
|
164
147
|
|
|
165
|
-
|
|
166
|
-
return this._scrollElement.scrollHeight || Math.max(
|
|
167
|
-
document.body.scrollHeight,
|
|
168
|
-
document.documentElement.scrollHeight
|
|
169
|
-
)
|
|
148
|
+
return new IntersectionObserver(entries => this._observerCallback(entries), options)
|
|
170
149
|
}
|
|
171
150
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
151
|
+
// The logic of selection
|
|
152
|
+
_observerCallback(entries) {
|
|
153
|
+
const targetElement = entry => this._targetLinks.get(`#${entry.target.id}`)
|
|
154
|
+
const activate = entry => {
|
|
155
|
+
this._previousScrollData.visibleEntryTop = entry.target.offsetTop
|
|
156
|
+
this._process(targetElement(entry))
|
|
157
|
+
}
|
|
177
158
|
|
|
178
|
-
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
const maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight()
|
|
159
|
+
const parentScrollTop = (this._rootElement || document.documentElement).scrollTop
|
|
160
|
+
const userScrollsDown = parentScrollTop >= this._previousScrollData.parentScrollTop
|
|
161
|
+
this._previousScrollData.parentScrollTop = parentScrollTop
|
|
182
162
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
163
|
+
for (const entry of entries) {
|
|
164
|
+
if (!entry.isIntersecting) {
|
|
165
|
+
this._activeTarget = null
|
|
166
|
+
this._clearActiveClass(targetElement(entry))
|
|
167
|
+
|
|
168
|
+
continue
|
|
169
|
+
}
|
|
186
170
|
|
|
187
|
-
|
|
188
|
-
|
|
171
|
+
const entryIsLowerThanPrevious = entry.target.offsetTop >= this._previousScrollData.visibleEntryTop
|
|
172
|
+
// if we are scrolling down, pick the bigger offsetTop
|
|
173
|
+
if (userScrollsDown && entryIsLowerThanPrevious) {
|
|
174
|
+
activate(entry)
|
|
175
|
+
// if parent isn't scrolled, let's keep the first visible item, breaking the iteration
|
|
176
|
+
if (!parentScrollTop) {
|
|
177
|
+
return
|
|
178
|
+
}
|
|
189
179
|
|
|
190
|
-
|
|
191
|
-
this._activate(target)
|
|
180
|
+
continue
|
|
192
181
|
}
|
|
193
182
|
|
|
194
|
-
|
|
183
|
+
// if we are scrolling up, pick the smallest offsetTop
|
|
184
|
+
if (!userScrollsDown && !entryIsLowerThanPrevious) {
|
|
185
|
+
activate(entry)
|
|
186
|
+
}
|
|
195
187
|
}
|
|
188
|
+
}
|
|
196
189
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
190
|
+
// TODO: v6 Only for backwards compatibility reasons. Use rootMargin only
|
|
191
|
+
_getRootMargin() {
|
|
192
|
+
return this._config.offset ? `${this._config.offset}px 0px -30%` : this._config.rootMargin
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
_initializeTargetsAndObservables() {
|
|
196
|
+
this._targetLinks = new Map()
|
|
197
|
+
this._observableSections = new Map()
|
|
198
|
+
|
|
199
|
+
const targetLinks = SelectorEngine.find(SELECTOR_TARGET_LINKS, this._config.target)
|
|
202
200
|
|
|
203
|
-
for (
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
201
|
+
for (const anchor of targetLinks) {
|
|
202
|
+
// ensure that the anchor has an id and is not disabled
|
|
203
|
+
if (!anchor.hash || isDisabled(anchor)) {
|
|
204
|
+
continue
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const observableSection = SelectorEngine.findOne(anchor.hash, this._element)
|
|
207
208
|
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
// ensure that the observableSection exists & is visible
|
|
210
|
+
if (isVisible(observableSection)) {
|
|
211
|
+
this._targetLinks.set(anchor.hash, anchor)
|
|
212
|
+
this._observableSections.set(anchor.hash, observableSection)
|
|
210
213
|
}
|
|
211
214
|
}
|
|
212
215
|
}
|
|
213
216
|
|
|
214
|
-
|
|
215
|
-
this._activeTarget
|
|
216
|
-
|
|
217
|
-
|
|
217
|
+
_process(target) {
|
|
218
|
+
if (this._activeTarget === target) {
|
|
219
|
+
return
|
|
220
|
+
}
|
|
218
221
|
|
|
219
|
-
|
|
220
|
-
|
|
222
|
+
this._clearActiveClass(this._config.target)
|
|
223
|
+
this._activeTarget = target
|
|
224
|
+
target.classList.add(CLASS_NAME_ACTIVE)
|
|
225
|
+
this._activateParents(target)
|
|
221
226
|
|
|
222
|
-
|
|
227
|
+
EventHandler.trigger(this._element, EVENT_ACTIVATE, { relatedTarget: target })
|
|
228
|
+
}
|
|
223
229
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
_activateParents(target) {
|
|
231
|
+
// Activate dropdown parents
|
|
232
|
+
if (target.classList.contains(CLASS_NAME_DROPDOWN_ITEM)) {
|
|
233
|
+
SelectorEngine.findOne(SELECTOR_DROPDOWN_TOGGLE, target.closest(SELECTOR_DROPDOWN))
|
|
227
234
|
.classList.add(CLASS_NAME_ACTIVE)
|
|
228
|
-
|
|
229
|
-
SelectorEngine.parents(link, SELECTOR_NAV_LIST_GROUP)
|
|
230
|
-
.forEach(listGroup => {
|
|
231
|
-
// Set triggered links parents as active
|
|
232
|
-
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
|
|
233
|
-
SelectorEngine.prev(listGroup, `${SELECTOR_NAV_LINKS}, ${SELECTOR_LIST_ITEMS}`)
|
|
234
|
-
.forEach(item => item.classList.add(CLASS_NAME_ACTIVE))
|
|
235
|
-
|
|
236
|
-
// Handle special case when .nav-link is inside .nav-item
|
|
237
|
-
SelectorEngine.prev(listGroup, SELECTOR_NAV_ITEMS)
|
|
238
|
-
.forEach(navItem => {
|
|
239
|
-
SelectorEngine.children(navItem, SELECTOR_NAV_LINKS)
|
|
240
|
-
.forEach(item => item.classList.add(CLASS_NAME_ACTIVE))
|
|
241
|
-
})
|
|
242
|
-
})
|
|
235
|
+
return
|
|
243
236
|
}
|
|
244
237
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
238
|
+
for (const listGroup of SelectorEngine.parents(target, SELECTOR_NAV_LIST_GROUP)) {
|
|
239
|
+
// Set triggered links parents as active
|
|
240
|
+
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
|
|
241
|
+
for (const item of SelectorEngine.prev(listGroup, SELECTOR_LINK_ITEMS)) {
|
|
242
|
+
item.classList.add(CLASS_NAME_ACTIVE)
|
|
243
|
+
}
|
|
244
|
+
}
|
|
248
245
|
}
|
|
249
246
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
247
|
+
_clearActiveClass(parent) {
|
|
248
|
+
parent.classList.remove(CLASS_NAME_ACTIVE)
|
|
249
|
+
|
|
250
|
+
const activeNodes = SelectorEngine.find(`${SELECTOR_TARGET_LINKS}.${CLASS_NAME_ACTIVE}`, parent)
|
|
251
|
+
for (const node of activeNodes) {
|
|
252
|
+
node.classList.remove(CLASS_NAME_ACTIVE)
|
|
253
|
+
}
|
|
254
254
|
}
|
|
255
255
|
|
|
256
256
|
// Static
|
|
257
|
-
|
|
258
257
|
static jQueryInterface(config) {
|
|
259
258
|
return this.each(function () {
|
|
260
259
|
const data = ScrollSpy.getOrCreateInstance(this, config)
|
|
@@ -263,7 +262,7 @@ class ScrollSpy extends BaseComponent {
|
|
|
263
262
|
return
|
|
264
263
|
}
|
|
265
264
|
|
|
266
|
-
if (
|
|
265
|
+
if (data[config] === undefined || config.startsWith('_') || config === 'constructor') {
|
|
267
266
|
throw new TypeError(`No method named "${config}"`)
|
|
268
267
|
}
|
|
269
268
|
|
|
@@ -273,21 +272,17 @@ class ScrollSpy extends BaseComponent {
|
|
|
273
272
|
}
|
|
274
273
|
|
|
275
274
|
/**
|
|
276
|
-
*
|
|
277
|
-
* Data Api implementation
|
|
278
|
-
* ------------------------------------------------------------------------
|
|
275
|
+
* Data API implementation
|
|
279
276
|
*/
|
|
280
277
|
|
|
281
278
|
EventHandler.on(window, EVENT_LOAD_DATA_API, () => {
|
|
282
|
-
SelectorEngine.find(SELECTOR_DATA_SPY)
|
|
283
|
-
.
|
|
279
|
+
for (const spy of SelectorEngine.find(SELECTOR_DATA_SPY)) {
|
|
280
|
+
ScrollSpy.getOrCreateInstance(spy)
|
|
281
|
+
}
|
|
284
282
|
})
|
|
285
283
|
|
|
286
284
|
/**
|
|
287
|
-
* ------------------------------------------------------------------------
|
|
288
285
|
* jQuery
|
|
289
|
-
* ------------------------------------------------------------------------
|
|
290
|
-
* add .ScrollSpy to jQuery only if jQuery is present
|
|
291
286
|
*/
|
|
292
287
|
|
|
293
288
|
defineJQueryPlugin(ScrollSpy)
|