bootstrap-italia 2.13.4 → 2.15.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/dist/_virtual/_commonjsHelpers.js +6 -0
- package/dist/_virtual/_commonjsHelpers.js.map +1 -0
- package/dist/bootstrap-italia.esm.js +1 -2
- package/dist/bootstrap-italia.esm.js.map +1 -1
- package/dist/css/bootstrap-italia.min.css +1 -1
- package/dist/css/bootstrap-italia.min.css.map +1 -1
- package/dist/js/bootstrap-italia.bundle.min.js +15 -9
- package/dist/js/bootstrap-italia.min.js +4 -4
- package/dist/plugins/back-to-top.js +0 -6
- package/dist/plugins/back-to-top.js.map +1 -1
- package/dist/plugins/button.js +3 -3
- package/dist/plugins/button.js.map +1 -1
- package/dist/plugins/carousel.js +183 -402
- package/dist/plugins/carousel.js.map +1 -1
- package/dist/plugins/forward.js.map +1 -1
- package/dist/plugins/header-sticky.js +1 -7
- package/dist/plugins/header-sticky.js.map +1 -1
- package/dist/plugins/input-label.js +5 -1
- package/dist/plugins/input-label.js.map +1 -1
- package/dist/plugins/input-number.js +5 -7
- package/dist/plugins/input-number.js.map +1 -1
- package/dist/plugins/masonry.js +8 -1
- package/dist/plugins/masonry.js.map +1 -1
- package/dist/plugins/navbar-collapsible.js +120 -139
- package/dist/plugins/navbar-collapsible.js.map +1 -1
- package/dist/plugins/navscroll.js +27 -3
- package/dist/plugins/navscroll.js.map +1 -1
- package/dist/plugins/select-autocomplete.js +66 -17
- package/dist/plugins/select-autocomplete.js.map +1 -1
- package/dist/plugins/tooltip.js +10 -0
- package/dist/plugins/tooltip.js.map +1 -1
- package/dist/plugins/track-focus.js +0 -6
- package/dist/plugins/track-focus.js.map +1 -1
- package/dist/plugins/util/focustrap.js +23 -3
- package/dist/plugins/util/focustrap.js.map +1 -1
- package/dist/plugins/vendor/accessible-autocomplete.js +9 -0
- package/dist/plugins/vendor/accessible-autocomplete.js.map +1 -0
- package/dist/svg/sprites.svg +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +2 -3
- package/src/js/bootstrap-italia.entry.js +0 -2
- package/src/js/bootstrap-italia.esm.js +1 -2
- package/src/js/icons.js +9 -0
- package/src/js/plugins/back-to-top.js +0 -6
- package/src/js/plugins/button.js +3 -3
- package/src/js/plugins/carousel.js +184 -402
- package/src/js/plugins/forward.js +0 -1
- package/src/js/plugins/header-sticky.js +1 -7
- package/src/js/plugins/input-label.js +5 -1
- package/src/js/plugins/input-number.js +5 -7
- package/src/js/plugins/masonry.js +8 -1
- package/src/js/plugins/navbar-collapsible.js +120 -141
- package/src/js/plugins/navscroll.js +27 -3
- package/src/js/plugins/select-autocomplete.js +67 -17
- package/src/js/plugins/tooltip.js +10 -0
- package/src/js/plugins/track-focus.js +0 -6
- package/src/js/plugins/util/focustrap.js +23 -3
- package/src/js/plugins/util/pageScroll.js +1 -1
- package/src/js/plugins/vendor/accessible-autocomplete.js +1 -0
- package/src/js/version.js +1 -1
- package/src/scss/base/_variables.scss +1 -1
- package/src/scss/base/_version.scss +1 -1
- package/src/scss/components/_buttons.scss +1 -1
- package/src/scss/components/_carousel.scss +7 -235
- package/src/scss/components/_navigation.scss +22 -7
- package/src/scss/components/_tab.scss +4 -4
- package/src/scss/forms/_accessible-autocomplete.scss +0 -19
- package/src/scss/forms/_form-input-number.scss +1 -1
- package/src/scss/forms/_form-input-upload.scss +1 -1
- package/src/scss/forms/_form-toggles.scss +1 -1
- package/src/scss/forms/_forms.scss +2 -1
- package/src/scss/forms/_just-validate.scss +4 -4
- package/src/scss/utilities/focus.scss +26 -16
- package/src/svg/it-bluesky.svg +4 -0
- package/src/svg/it-car.svg +4 -0
- package/src/svg/it-cart.svg +5 -0
- package/src/svg/it-file-docx.svg +12 -0
- package/src/svg/it-file-image.svg +5 -0
- package/src/svg/it-file-signed.svg +16 -0
- package/src/svg/it-file-xlsx.svg +11 -0
- package/src/svg/it-sign.svg +8 -0
- package/src/svg/it-spotify.svg +4 -0
- package/types/index.d.ts +0 -2
- package/types/plugins/carousel.d.ts +42 -2
- package/dist/plugins/carousel-bi.js +0 -226
- package/dist/plugins/carousel-bi.js.map +0 -1
- package/dist/plugins/util/pageScroll.js +0 -45
- package/dist/plugins/util/pageScroll.js.map +0 -1
- package/dist/plugins/util/swipe.js +0 -150
- package/dist/plugins/util/swipe.js.map +0 -1
- package/src/js/plugins/carousel-bi.js +0 -225
- package/types/plugins/carousel-bi.d.ts +0 -57
|
@@ -33,11 +33,8 @@ const SELECTOR_BTN = 'button[class^="input-number-"]'
|
|
|
33
33
|
class InputNumber extends BaseComponent {
|
|
34
34
|
constructor(element) {
|
|
35
35
|
super(element)
|
|
36
|
-
|
|
37
36
|
this._wrapperElement = this._element.closest(SELECTOR_WRAPPER)
|
|
38
|
-
|
|
39
37
|
this._label = new InputLabel(element)
|
|
40
|
-
|
|
41
38
|
this._init()
|
|
42
39
|
this._bindEvents()
|
|
43
40
|
}
|
|
@@ -48,8 +45,6 @@ class InputNumber extends BaseComponent {
|
|
|
48
45
|
return NAME
|
|
49
46
|
}
|
|
50
47
|
|
|
51
|
-
// Public
|
|
52
|
-
|
|
53
48
|
// Private
|
|
54
49
|
_init() {
|
|
55
50
|
if (this._wrapperElement) {
|
|
@@ -83,7 +78,10 @@ class InputNumber extends BaseComponent {
|
|
|
83
78
|
}
|
|
84
79
|
|
|
85
80
|
_incrDecr(isDecr) {
|
|
86
|
-
|
|
81
|
+
let inputVal = 0
|
|
82
|
+
if (this._element.disabled || this._element.readonly) {
|
|
83
|
+
return
|
|
84
|
+
}
|
|
87
85
|
if (this._element.value !== '') inputVal = parseFloat(this._element.value)
|
|
88
86
|
|
|
89
87
|
if (!isNaN(inputVal)) {
|
|
@@ -137,7 +135,7 @@ const createInput = (element) => {
|
|
|
137
135
|
|
|
138
136
|
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
139
137
|
document.addEventListener('DOMContentLoaded', function () {
|
|
140
|
-
|
|
138
|
+
let frmel = document.querySelectorAll(SELECTOR_INPUT + ', label')
|
|
141
139
|
frmel.forEach(function (item) {
|
|
142
140
|
const target = InputLabel.getInputFromLabel(item) || item
|
|
143
141
|
createInput(target)
|
|
@@ -54,6 +54,13 @@ class Masonry extends BaseComponent {
|
|
|
54
54
|
super.dispose()
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
// Public
|
|
58
|
+
layout() {
|
|
59
|
+
if (this._masonry) {
|
|
60
|
+
this._masonry.layout()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
57
64
|
// Private
|
|
58
65
|
_getConfig(config) {
|
|
59
66
|
config = {
|
|
@@ -86,7 +93,7 @@ class Masonry extends BaseComponent {
|
|
|
86
93
|
_initMasonry() {
|
|
87
94
|
const config = this._config
|
|
88
95
|
config.container = this._element
|
|
89
|
-
this._masonry = new MiniMasonry(config)
|
|
96
|
+
this._masonry = new MiniMasonry(config)
|
|
90
97
|
}
|
|
91
98
|
|
|
92
99
|
_createLoader() {
|
|
@@ -7,14 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import BaseComponent from './base-component.js'
|
|
10
|
-
|
|
11
10
|
import { getElementFromSelector, isVisible, reflow } from './util/index'
|
|
12
11
|
import EventHandler from './dom/event-handler'
|
|
13
12
|
import SelectorEngine from './dom/selector-engine'
|
|
14
|
-
|
|
15
13
|
import { isScreenMobile } from './util/device'
|
|
16
|
-
import
|
|
17
|
-
import
|
|
14
|
+
import ScrollBarHelper from './util/scrollbar'
|
|
15
|
+
import FocusTrap from './util/focustrap'
|
|
16
|
+
import Backdrop from './util/backdrop'
|
|
18
17
|
|
|
19
18
|
const NAME = 'navbarcollapsible'
|
|
20
19
|
const DATA_KEY = 'bs.navbarcollapsible'
|
|
@@ -23,7 +22,6 @@ const DATA_API_KEY = '.data-api'
|
|
|
23
22
|
|
|
24
23
|
const EVENT_CLICK_DATA_API = `click${EVENT_KEY}${DATA_API_KEY}`
|
|
25
24
|
const EVENT_CLICK = `click${EVENT_KEY}`
|
|
26
|
-
const EVENT_KEYUP = `keyup${EVENT_KEY}`
|
|
27
25
|
const EVENT_KEYDOWN = `keydown${EVENT_KEY}`
|
|
28
26
|
const EVENT_HIDE = `hide${EVENT_KEY}`
|
|
29
27
|
const EVENT_HIDDEN = `hidden${EVENT_KEY}`
|
|
@@ -31,54 +29,88 @@ const EVENT_SHOW = `show${EVENT_KEY}`
|
|
|
31
29
|
const EVENT_SHOWN = `shown${EVENT_KEY}`
|
|
32
30
|
const EVENT_RESIZE = `resize${EVENT_KEY}`
|
|
33
31
|
|
|
34
|
-
const
|
|
32
|
+
const CLASS_NAME_OPEN = 'navbar-open'
|
|
35
33
|
const CLASS_NAME_SHOW = 'show'
|
|
36
34
|
const CLASS_NAME_EXPANDED = 'expanded'
|
|
37
35
|
|
|
38
36
|
const SELECTOR_DATA_TOGGLE = '[data-bs-toggle="navbarcollapsible"]'
|
|
39
|
-
|
|
40
|
-
//const SELECTOR_NAVBAR = '.navbar-collapsable'
|
|
41
37
|
const SELECTOR_BTN_CLOSE = '.close-div button'
|
|
42
38
|
const SELECTOR_BTN_MENU_CLOSE = '.close-menu'
|
|
43
39
|
const SELECTOR_BTN_BACK = '.it-back-button'
|
|
44
|
-
const SELECTOR_OVERLAY = '.overlay'
|
|
45
40
|
const SELECTOR_MENU_WRAPPER = '.menu-wrapper'
|
|
46
41
|
const SELECTOR_NAVLINK = '.nav-link'
|
|
47
42
|
const SELECTOR_MEGAMENUNAVLINK = '.nav-item .list-item'
|
|
48
43
|
const SELECTOR_HEADINGLINK = '.it-heading-link'
|
|
49
44
|
const SELECTOR_FOOTERLINK = '.it-footer-link'
|
|
50
45
|
|
|
46
|
+
const Default = {
|
|
47
|
+
backdrop: true,
|
|
48
|
+
focus: true,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const DefaultType = {
|
|
52
|
+
backdrop: '(boolean|string)',
|
|
53
|
+
focus: 'boolean',
|
|
54
|
+
}
|
|
55
|
+
|
|
51
56
|
class NavBarCollapsible extends BaseComponent {
|
|
52
|
-
constructor(element) {
|
|
53
|
-
super(element)
|
|
57
|
+
constructor(element, config) {
|
|
58
|
+
super(element, config)
|
|
59
|
+
|
|
60
|
+
this._mainElement = SelectorEngine.findOne('main')
|
|
61
|
+
this._isNavbarOutsideMain = this._mainElement && !this._mainElement.contains(this._element)
|
|
62
|
+
this._parentElement = this._element.parentNode
|
|
54
63
|
|
|
55
64
|
this._isShown = this._element.classList.contains(CLASS_NAME_EXPANDED)
|
|
56
|
-
this._isTransitioning = false
|
|
57
65
|
|
|
58
|
-
this.
|
|
59
|
-
|
|
66
|
+
if (!this._element.getAttribute('tabindex')) {
|
|
67
|
+
this._element.setAttribute('tabindex', '-1')
|
|
68
|
+
}
|
|
60
69
|
|
|
61
|
-
this.
|
|
70
|
+
this._backdrop = this._initializeBackDrop()
|
|
71
|
+
this._focustrap = this._initializeFocusTrap()
|
|
72
|
+
this._scrollBar = new ScrollBarHelper()
|
|
73
|
+
this._isTransitioning = false
|
|
74
|
+
this._isMobile = isScreenMobile()
|
|
62
75
|
|
|
63
76
|
this._btnClose = SelectorEngine.findOne(SELECTOR_BTN_CLOSE, this._element)
|
|
64
77
|
this._btnBack = SelectorEngine.findOne(SELECTOR_BTN_BACK, this._element)
|
|
65
78
|
this._menuWrapper = SelectorEngine.findOne(SELECTOR_MENU_WRAPPER, this._element)
|
|
66
|
-
|
|
67
|
-
this._setOverlay()
|
|
79
|
+
|
|
68
80
|
this._menuItems = SelectorEngine.find(
|
|
69
81
|
[SELECTOR_NAVLINK, SELECTOR_MEGAMENUNAVLINK, SELECTOR_HEADINGLINK, SELECTOR_FOOTERLINK, SELECTOR_BTN_MENU_CLOSE].join(','),
|
|
70
82
|
this._element
|
|
71
83
|
)
|
|
72
84
|
|
|
85
|
+
this._toggleButton =
|
|
86
|
+
SelectorEngine.findOne(`${SELECTOR_DATA_TOGGLE}[data-bs-target="#${this._element.id}"]`) ||
|
|
87
|
+
SelectorEngine.findOne(`${SELECTOR_DATA_TOGGLE}[href="#${this._element.id}"]`)
|
|
88
|
+
|
|
89
|
+
if (this._toggleButton) {
|
|
90
|
+
if (!this._toggleButton.getAttribute('aria-expanded')) {
|
|
91
|
+
this._toggleButton.setAttribute('aria-expanded', this._isShown ? 'true' : 'false')
|
|
92
|
+
}
|
|
93
|
+
}
|
|
73
94
|
this._bindEvents()
|
|
74
95
|
}
|
|
96
|
+
|
|
75
97
|
// Getters
|
|
98
|
+
static get Default() {
|
|
99
|
+
return Default
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
static get DefaultType() {
|
|
103
|
+
return DefaultType
|
|
104
|
+
}
|
|
76
105
|
|
|
77
106
|
static get NAME() {
|
|
78
107
|
return NAME
|
|
79
108
|
}
|
|
80
109
|
|
|
81
110
|
// Public
|
|
111
|
+
toggle(relatedTarget) {
|
|
112
|
+
this._isShown ? this.hide() : this.show(relatedTarget)
|
|
113
|
+
}
|
|
82
114
|
|
|
83
115
|
show(relatedTarget) {
|
|
84
116
|
if (this._isShown || this._isTransitioning) {
|
|
@@ -93,14 +125,22 @@ class NavBarCollapsible extends BaseComponent {
|
|
|
93
125
|
return
|
|
94
126
|
}
|
|
95
127
|
|
|
128
|
+
this._isShown = true
|
|
129
|
+
this._isTransitioning = true
|
|
130
|
+
this._scrollBar.hide()
|
|
131
|
+
|
|
96
132
|
if (this._btnBack) {
|
|
97
133
|
this._btnBack.classList.add(CLASS_NAME_SHOW)
|
|
98
134
|
}
|
|
99
135
|
|
|
100
|
-
|
|
136
|
+
document.body.classList.add(CLASS_NAME_OPEN)
|
|
101
137
|
|
|
102
|
-
|
|
138
|
+
this._backdrop.show()
|
|
103
139
|
this._showElement()
|
|
140
|
+
|
|
141
|
+
if (this._toggleButton) {
|
|
142
|
+
this._toggleButton.setAttribute('aria-expanded', 'true')
|
|
143
|
+
}
|
|
104
144
|
}
|
|
105
145
|
|
|
106
146
|
hide() {
|
|
@@ -116,45 +156,64 @@ class NavBarCollapsible extends BaseComponent {
|
|
|
116
156
|
|
|
117
157
|
this._isShown = false
|
|
118
158
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (isAnimated) {
|
|
122
|
-
this._isTransitioning = true
|
|
123
|
-
}
|
|
159
|
+
this._isTransitioning = true
|
|
160
|
+
this._focustrap.deactivate()
|
|
124
161
|
|
|
125
162
|
if (this._btnBack) {
|
|
126
163
|
this._btnBack.classList.remove(CLASS_NAME_SHOW)
|
|
127
164
|
}
|
|
128
|
-
if (this._overlay) {
|
|
129
|
-
this._overlay.classList.remove(CLASS_NAME_SHOW)
|
|
130
|
-
}
|
|
131
165
|
|
|
132
166
|
this._element.classList.remove(CLASS_NAME_EXPANDED)
|
|
133
167
|
|
|
134
|
-
|
|
135
|
-
this._queueCallback(() => this._hideElement(), this._menuWrapper, isAnimated)
|
|
136
|
-
}
|
|
168
|
+
this._backdrop.hide()
|
|
137
169
|
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
this._queueCallback(() => this._hideElement(), this._menuWrapper, this._isAnimated())
|
|
171
|
+
|
|
172
|
+
if (this._toggleButton) {
|
|
173
|
+
this._toggleButton.setAttribute('aria-expanded', 'false')
|
|
174
|
+
}
|
|
140
175
|
}
|
|
141
176
|
|
|
142
177
|
dispose() {
|
|
143
178
|
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
144
179
|
EventHandler.off(window, EVENT_RESIZE)
|
|
145
|
-
|
|
180
|
+
EventHandler.off(document, EVENT_KEYDOWN)
|
|
146
181
|
}
|
|
182
|
+
this._backdrop.dispose()
|
|
183
|
+
|
|
184
|
+
this._focustrap.deactivate()
|
|
185
|
+
super.dispose()
|
|
147
186
|
}
|
|
148
187
|
|
|
149
|
-
|
|
188
|
+
_initializeBackDrop() {
|
|
189
|
+
return new Backdrop({
|
|
190
|
+
isVisible: Boolean(this._config.backdrop), // 'static' option will be translated to true, and booleans will keep their value,
|
|
191
|
+
isAnimated: this._isAnimated(),
|
|
192
|
+
className: 'navbar-backdrop',
|
|
193
|
+
rootElement: this._parentElement,
|
|
194
|
+
clickCallback: () => {
|
|
195
|
+
this.hide()
|
|
196
|
+
},
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
_initializeFocusTrap() {
|
|
201
|
+
return new FocusTrap({
|
|
202
|
+
trapElement: this._element,
|
|
203
|
+
initialFocus: () => this._btnClose || this._element.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
|
|
204
|
+
})
|
|
205
|
+
}
|
|
150
206
|
|
|
207
|
+
// Private
|
|
151
208
|
_bindEvents() {
|
|
152
209
|
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
153
210
|
EventHandler.on(window, EVENT_RESIZE, () => this._onResize())
|
|
211
|
+
EventHandler.on(document, EVENT_KEYDOWN, (evt) => {
|
|
212
|
+
if (this._isShown && evt.key === 'Escape') {
|
|
213
|
+
this.hide()
|
|
214
|
+
}
|
|
215
|
+
})
|
|
154
216
|
|
|
155
|
-
if (this._overlay) {
|
|
156
|
-
EventHandler.on(this._overlay, EVENT_CLICK, () => this.hide())
|
|
157
|
-
}
|
|
158
217
|
EventHandler.on(this._btnClose, EVENT_CLICK, (evt) => {
|
|
159
218
|
evt.preventDefault()
|
|
160
219
|
this.hide()
|
|
@@ -163,11 +222,8 @@ class NavBarCollapsible extends BaseComponent {
|
|
|
163
222
|
evt.preventDefault()
|
|
164
223
|
this.hide()
|
|
165
224
|
})
|
|
166
|
-
|
|
167
225
|
this._menuItems.forEach((item) => {
|
|
168
226
|
EventHandler.on(item, EVENT_KEYDOWN, (evt) => this._isMobile && this._onMenuItemKeyDown(evt))
|
|
169
|
-
EventHandler.on(item, EVENT_KEYUP, (evt) => this._isMobile && this._onMenuItemKeyUp(evt))
|
|
170
|
-
EventHandler.on(item, EVENT_CLICK, (evt) => this._isMobile && this._onMenuItemClick(evt))
|
|
171
227
|
})
|
|
172
228
|
}
|
|
173
229
|
}
|
|
@@ -176,30 +232,14 @@ class NavBarCollapsible extends BaseComponent {
|
|
|
176
232
|
this._isMobile = isScreenMobile()
|
|
177
233
|
}
|
|
178
234
|
|
|
179
|
-
_onMenuItemKeyUp(evt) {
|
|
180
|
-
if (evt.key === 'Shift') {
|
|
181
|
-
this._isKeyShift = false
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
235
|
_onMenuItemKeyDown(evt) {
|
|
185
|
-
if (evt.key === '
|
|
186
|
-
this.
|
|
187
|
-
}
|
|
188
|
-
if (evt.key === 'Tab') {
|
|
189
|
-
evt.preventDefault()
|
|
190
|
-
this._focusNext()
|
|
236
|
+
if (evt.key === 'Escape') {
|
|
237
|
+
this.hide()
|
|
191
238
|
}
|
|
192
239
|
}
|
|
193
|
-
/**
|
|
194
|
-
* Update the last focused element when an interactive element is clicked
|
|
195
|
-
*/
|
|
196
|
-
_onMenuItemClick(evt) {
|
|
197
|
-
this.currItemIdx = getElementIndex(evt.currentTarget, this._menuItems)
|
|
198
|
-
}
|
|
199
240
|
|
|
200
241
|
_isAnimated() {
|
|
201
|
-
|
|
202
|
-
return true //this._element.classList.contains(CLASS_NAME_EXPANDED)
|
|
242
|
+
return true
|
|
203
243
|
}
|
|
204
244
|
|
|
205
245
|
_isElementHidden(element) {
|
|
@@ -207,108 +247,47 @@ class NavBarCollapsible extends BaseComponent {
|
|
|
207
247
|
}
|
|
208
248
|
|
|
209
249
|
_showElement() {
|
|
210
|
-
const isAnimated = this._isAnimated()
|
|
211
|
-
|
|
212
250
|
this._element.style.display = 'block'
|
|
213
|
-
this._element.
|
|
214
|
-
|
|
215
|
-
//this._element.setAttribute('role', 'dialog')
|
|
216
|
-
if (this._overlay) {
|
|
217
|
-
this._overlay.style.display = 'block'
|
|
251
|
+
if (!this._element.getAttribute('aria-label') && !this._element.getAttribute('aria-labelledby')) {
|
|
252
|
+
this._element.setAttribute('aria-label', 'Menu')
|
|
218
253
|
}
|
|
254
|
+
this._element.setAttribute('aria-modal', true)
|
|
255
|
+
this._element.setAttribute('role', 'dialog')
|
|
219
256
|
|
|
220
|
-
if (
|
|
221
|
-
|
|
257
|
+
if (this._mainElement && this._isNavbarOutsideMain) {
|
|
258
|
+
this._mainElement.setAttribute('inert', '')
|
|
222
259
|
}
|
|
223
260
|
|
|
261
|
+
reflow(this._element)
|
|
262
|
+
|
|
224
263
|
this._element.classList.add(CLASS_NAME_EXPANDED)
|
|
225
|
-
if (this._overlay) {
|
|
226
|
-
this._overlay.classList.add(CLASS_NAME_SHOW)
|
|
227
|
-
}
|
|
228
264
|
|
|
229
265
|
const transitionComplete = () => {
|
|
230
|
-
this.
|
|
231
|
-
|
|
232
|
-
if (firstItem.item) {
|
|
233
|
-
firstItem.item.focus()
|
|
234
|
-
this._currItemIdx = firstItem.index
|
|
266
|
+
if (this._config.focus) {
|
|
267
|
+
this._focustrap.activate()
|
|
235
268
|
}
|
|
269
|
+
this._isTransitioning = false
|
|
236
270
|
EventHandler.trigger(this._element, EVENT_SHOWN)
|
|
237
271
|
}
|
|
238
272
|
|
|
239
|
-
this._queueCallback(transitionComplete, this._menuWrapper,
|
|
273
|
+
this._queueCallback(transitionComplete, this._menuWrapper, this._isAnimated())
|
|
240
274
|
}
|
|
241
275
|
|
|
242
276
|
_hideElement() {
|
|
243
|
-
if (this._overlay) {
|
|
244
|
-
this._overlay.style.display = 'none'
|
|
245
|
-
}
|
|
246
|
-
|
|
247
277
|
this._element.style.display = 'none'
|
|
248
|
-
this._element.
|
|
249
|
-
this._element.removeAttribute('
|
|
250
|
-
//this._element.removeAttribute('aria-modal')
|
|
251
|
-
//this._element.removeAttribute('role')
|
|
252
|
-
this._isTransitioning = false
|
|
253
|
-
EventHandler.trigger(this._element, EVENT_HIDDEN)
|
|
254
|
-
}
|
|
278
|
+
this._element.removeAttribute('aria-modal')
|
|
279
|
+
this._element.removeAttribute('role')
|
|
255
280
|
|
|
256
|
-
|
|
257
|
-
this._overlay = SelectorEngine.findOne(SELECTOR_OVERLAY, this._element)
|
|
258
|
-
if (this._isAnimated) {
|
|
259
|
-
this._overlay.classList.add(CLASS_NAME_FADE)
|
|
260
|
-
}
|
|
261
|
-
}
|
|
281
|
+
document.body.classList.remove(CLASS_NAME_OPEN)
|
|
262
282
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
*/
|
|
266
|
-
_focusNext() {
|
|
267
|
-
let nextIdx = this._currItemIdx + (this._isKeyShift ? -1 : 1)
|
|
268
|
-
if (nextIdx < 0) {
|
|
269
|
-
nextIdx = this._menuItems.length - 1
|
|
270
|
-
} else if (nextIdx >= this._menuItems.length) {
|
|
271
|
-
nextIdx = 0
|
|
272
|
-
}
|
|
273
|
-
const target = this._getNextVisibleItem(nextIdx, this._isKeyShift)
|
|
274
|
-
if (target.item) {
|
|
275
|
-
target.item.focus()
|
|
276
|
-
this._currItemIdx = target.index
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Get the next focusable element from a starting point
|
|
281
|
-
* @param {int} start - the index of the array of the elements as starting point (included)
|
|
282
|
-
* @param {boolean} wayTop - the array search direction (true: bottom to top, false: top to bottom)
|
|
283
|
-
* @returns {Object} the item found and its index in the array
|
|
284
|
-
*/
|
|
285
|
-
_getNextVisibleItem(start, wayTop) {
|
|
286
|
-
let found = null
|
|
287
|
-
let foundIdx = null
|
|
288
|
-
|
|
289
|
-
let i = start
|
|
290
|
-
let incr = wayTop ? -1 : 1
|
|
291
|
-
let firstCheck = false
|
|
292
|
-
while (!found && (i != start || !firstCheck)) {
|
|
293
|
-
if (i == start) {
|
|
294
|
-
firstCheck = true
|
|
295
|
-
}
|
|
296
|
-
if (!this._isElementHidden(this._menuItems[i])) {
|
|
297
|
-
found = this._menuItems[i]
|
|
298
|
-
foundIdx = i
|
|
299
|
-
}
|
|
300
|
-
i = i + incr
|
|
301
|
-
if (i < 0) {
|
|
302
|
-
i = this._menuItems.length - 1
|
|
303
|
-
} else if (i >= this._menuItems.length) {
|
|
304
|
-
i = 0
|
|
305
|
-
}
|
|
283
|
+
if (this._mainElement && this._isNavbarOutsideMain) {
|
|
284
|
+
this._mainElement.removeAttribute('inert')
|
|
306
285
|
}
|
|
307
286
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
287
|
+
this._scrollBar.reset()
|
|
288
|
+
this._isTransitioning = false
|
|
289
|
+
|
|
290
|
+
EventHandler.trigger(this._element, EVENT_HIDDEN)
|
|
312
291
|
}
|
|
313
292
|
}
|
|
314
293
|
|
|
@@ -25,6 +25,7 @@ const SELECTOR_TOGGLER = '.custom-navbar-toggler'
|
|
|
25
25
|
const SELECTOR_TOGGLER_ICON = '.it-list'
|
|
26
26
|
const SELECTOR_COLLAPSIBLE = '.navbar-collapsable'
|
|
27
27
|
const SELECTOR_PROGRESS_BAR = '.it-navscroll-progressbar'
|
|
28
|
+
const SELECTOR_MENU_WRAPPER = '.menu-wrapper'
|
|
28
29
|
|
|
29
30
|
const Default = {
|
|
30
31
|
scrollPadding: 10,
|
|
@@ -44,6 +45,11 @@ class NavScroll extends BaseComponent {
|
|
|
44
45
|
this._callbackQueue = []
|
|
45
46
|
this._scrollCb = null
|
|
46
47
|
|
|
48
|
+
const menuWrapper = SelectorEngine.findOne(SELECTOR_MENU_WRAPPER, this._element)
|
|
49
|
+
if (menuWrapper && !menuWrapper.hasAttribute('tabindex')) {
|
|
50
|
+
menuWrapper.setAttribute('tabindex', '-1')
|
|
51
|
+
}
|
|
52
|
+
|
|
47
53
|
this._bindEvents()
|
|
48
54
|
}
|
|
49
55
|
// Getters
|
|
@@ -147,13 +153,31 @@ class NavScroll extends BaseComponent {
|
|
|
147
153
|
}
|
|
148
154
|
|
|
149
155
|
_scrollToHash(hash) {
|
|
150
|
-
|
|
156
|
+
if (!hash || hash === '#') {
|
|
157
|
+
// Validate hash to prevent errors
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
const target = this._sectionContainer // Fallback: when container is null, omit the second parameter entirely
|
|
161
|
+
? SelectorEngine.findOne(hash, this._sectionContainer)
|
|
162
|
+
: SelectorEngine.findOne(hash)
|
|
151
163
|
if (target) {
|
|
152
164
|
documentScrollTo(target.offsetTop - this._getScrollPadding(), {
|
|
153
165
|
duration: this._config.duration,
|
|
154
166
|
easing: this._config.easing,
|
|
155
|
-
|
|
156
|
-
|
|
167
|
+
complete: () => {
|
|
168
|
+
const isHeading = target.matches('h1, h2, h3, h4, h5, h6')
|
|
169
|
+
const needsTabIndex = !target.hasAttribute('tabindex')
|
|
170
|
+
if (needsTabIndex) {
|
|
171
|
+
target.setAttribute('tabindex', '-1')
|
|
172
|
+
}
|
|
173
|
+
target.focus({ preventScroll: true }) // preventScroll to avoid double scrolling
|
|
174
|
+
if (needsTabIndex && isHeading) {
|
|
175
|
+
// remove tabIndex for headings after 500ms
|
|
176
|
+
setTimeout(() => {
|
|
177
|
+
target.removeAttribute('tabindex')
|
|
178
|
+
}, 500)
|
|
179
|
+
}
|
|
180
|
+
},
|
|
157
181
|
})
|
|
158
182
|
|
|
159
183
|
if (history.pushState) {
|
|
@@ -6,30 +6,43 @@
|
|
|
6
6
|
* --------------------------------------------------------------------------
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import accessibleAutocomplete from 'accessible-autocomplete'
|
|
9
|
+
import accessibleAutocomplete from './vendor/accessible-autocomplete'
|
|
10
10
|
|
|
11
11
|
import BaseComponent from './base-component.js'
|
|
12
12
|
|
|
13
|
+
import InputLabel from './input-label'
|
|
14
|
+
|
|
13
15
|
const NAME = 'selectautocomplete'
|
|
14
16
|
|
|
15
17
|
function onClassChange(element, callback) {
|
|
16
18
|
const observer = new MutationObserver((mutations) => {
|
|
17
19
|
mutations.forEach((mutation) => {
|
|
18
20
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
|
19
|
-
callback(mutation.target)
|
|
21
|
+
callback(mutation.oldValue, mutation.target)
|
|
20
22
|
}
|
|
21
23
|
})
|
|
22
24
|
})
|
|
23
|
-
observer.observe(element, { attributes: true })
|
|
25
|
+
observer.observe(element, { attributes: true, attributeOldValue: true })
|
|
24
26
|
return observer.disconnect
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
class SelectAutocomplete extends BaseComponent {
|
|
28
30
|
constructor(element, config) {
|
|
29
31
|
super(element)
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
this._config =
|
|
32
|
+
|
|
33
|
+
this._config = config || {}
|
|
34
|
+
this._config.inputClasses = 'form-control'
|
|
35
|
+
this._config.showNoOptionsFound = true
|
|
36
|
+
this._config.hintClasses = 'app-hint'
|
|
37
|
+
this._config.autoselect = false
|
|
38
|
+
this._config.showAllValues = false
|
|
39
|
+
this._config.templates = undefined
|
|
40
|
+
this._config.confirmOnBlur = false
|
|
41
|
+
this._config.menuAttributes = {}
|
|
42
|
+
this._config.menuClasses = null
|
|
43
|
+
|
|
44
|
+
this._extraClasses = []
|
|
45
|
+
|
|
33
46
|
if (!this._config.tAssistiveHint)
|
|
34
47
|
this._config.tAssistiveHint = () =>
|
|
35
48
|
'Quando i risultati del completamento automatico sono disponibili, usa le frecce su e giù per rivedere e Invio per selezionare. Utenti di dispositivi touch, esplora tramite tocco o con gesti di scorrimento'
|
|
@@ -39,7 +52,7 @@ class SelectAutocomplete extends BaseComponent {
|
|
|
39
52
|
if (!this._config.tStatusNoResults) this._config.tStatusNoResults = () => 'Nessun risultato di ricerca'
|
|
40
53
|
if (!this._config.tStatusSelectedOption)
|
|
41
54
|
this._config.tStatusSelectedOption = (selectedOption, length, index) => `${selectedOption} ${index + 1} di ${length} è sottolineato`
|
|
42
|
-
if (!this._config.tStatusResults)
|
|
55
|
+
if (!this._config.tStatusResults) {
|
|
43
56
|
this._config.tStatusResults = (length, contentSelectedOption) => {
|
|
44
57
|
const words = {
|
|
45
58
|
result: length === 1 ? 'risultato' : 'risultati',
|
|
@@ -49,7 +62,10 @@ class SelectAutocomplete extends BaseComponent {
|
|
|
49
62
|
|
|
50
63
|
return `${length} ${words.result} ${words.is} ${words.available}. ${contentSelectedOption}`
|
|
51
64
|
}
|
|
52
|
-
|
|
65
|
+
}
|
|
66
|
+
if (typeof document !== 'undefined') {
|
|
67
|
+
this._enhance()
|
|
68
|
+
}
|
|
53
69
|
}
|
|
54
70
|
|
|
55
71
|
// Getters
|
|
@@ -60,20 +76,54 @@ class SelectAutocomplete extends BaseComponent {
|
|
|
60
76
|
|
|
61
77
|
// Private
|
|
62
78
|
_enhance() {
|
|
63
|
-
|
|
79
|
+
const inputId = this._config.id
|
|
80
|
+
const originalConfirm = this._config.onConfirm
|
|
81
|
+
|
|
82
|
+
this._config.onConfirm = (value) => {
|
|
83
|
+
document.getElementById(inputId).value = value
|
|
84
|
+
document.getElementById(inputId).dispatchEvent(new Event('input'))
|
|
85
|
+
if (originalConfirm) {
|
|
86
|
+
originalConfirm(value)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
accessibleAutocomplete(
|
|
91
|
+
Object.assign(
|
|
92
|
+
{},
|
|
93
|
+
{
|
|
94
|
+
element: this._element,
|
|
95
|
+
id: inputId,
|
|
96
|
+
},
|
|
97
|
+
this._config
|
|
98
|
+
)
|
|
99
|
+
)
|
|
64
100
|
setTimeout(() => {
|
|
65
|
-
|
|
66
|
-
|
|
101
|
+
this._inputField = document.getElementById(inputId)
|
|
102
|
+
this._label = new InputLabel(this._inputField)
|
|
103
|
+
this._inputField.addEventListener('focus', () => {
|
|
104
|
+
this._extraClasses.forEach((cls) => {
|
|
105
|
+
this._inputField.classList.add(cls)
|
|
106
|
+
})
|
|
107
|
+
this._extraClasses = []
|
|
108
|
+
})
|
|
109
|
+
this._inputField.addEventListener('blur', () => {
|
|
110
|
+
this._extraClasses.forEach((cls) => {
|
|
111
|
+
this._inputField.classList.add(cls)
|
|
112
|
+
})
|
|
113
|
+
this._extraClasses = []
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
onClassChange(this._inputField, (oldClasses) => {
|
|
117
|
+
this._extraClasses = []
|
|
118
|
+
if (oldClasses === this._inputField.classList.value) {
|
|
67
119
|
return
|
|
68
120
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!node.classList.contains('form-control')) {
|
|
73
|
-
node.classList.add('form-control')
|
|
121
|
+
oldClasses.split(' ').forEach((cls) => {
|
|
122
|
+
if (!cls.startsWith('autocomplete')) {
|
|
123
|
+
this._extraClasses.push(cls)
|
|
74
124
|
}
|
|
75
125
|
})
|
|
76
|
-
}
|
|
126
|
+
})
|
|
77
127
|
}, 100)
|
|
78
128
|
}
|
|
79
129
|
}
|
|
@@ -226,6 +226,16 @@ class Tooltip extends BaseComponent {
|
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
document.addEventListener(
|
|
230
|
+
'keyup',
|
|
231
|
+
(event) => {
|
|
232
|
+
if (event.key === 'Escape') {
|
|
233
|
+
this.hide()
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
{ once: true }
|
|
237
|
+
)
|
|
238
|
+
|
|
229
239
|
const complete = () => {
|
|
230
240
|
EventHandler.trigger(this._element, this.constructor.eventName(EVENT_SHOWN))
|
|
231
241
|
|