Skip to content

Commit 90db86a

Browse files
committed
feat(TimePicker): allows to append the dropdown to a specific element
1 parent 0002b1c commit 90db86a

File tree

4 files changed

+56
-15
lines changed

4 files changed

+56
-15
lines changed

docs/content/forms/time-picker.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ const timePickerList = timePickerElementList.map(timePickerEl => {
218218
| `cleaner` | boolean | `true` | Enables selection cleaner element. |
219219
| `confirmButtonLabel` | string | `'OK'` | Confirm button inner HTML |
220220
| `confirmButtonClasses` | array, string | `['btn', 'btn-sm', 'btn-primary']` | CSS class names that will be added to the confirm button |
221-
| `container` | string | `'dropdown'` | <p>Set container type for the component.</p><ul><li>`'dropdown'`</li><li>`'inline'`</li></ul>|
221+
| `container` | string, element, false | `false` | Appends the dropdown to a specific element. Example: `container: 'body'`. |
222222
| `disabled` | boolean | `false` | Toggle the disabled state for the component. |
223223
| `footer` | boolean | `true` | Toggle visibility of footer element. |
224224
| `hours` | array, function, null | `null` | Specify a list of available hours using an array, or customize the filtering of hours through a function. |
@@ -233,7 +233,7 @@ const timePickerList = timePickerElementList.map(timePickerEl => {
233233
| `size` | `'sm'`, `'lg'` | `null` | Size the component small or large. |
234234
| `time` | date, string, null | `null` | Default value of the component |
235235
| `valid` | boolean | `false` | Toggle the valid state for the component. |
236-
| `variant` | `'inline'`, `'roll'` | `'roll'` | Set the time picker variant to a roll or select. |
236+
| `variant` | `'roll'`, `'select'` | `'roll'` | Set the time picker variant to a roll or select. |
237237
{{< /bs-table >}}
238238
### Methods
239239

js/src/date-range-picker.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,10 @@ class DateRangePicker extends BaseComponent {
481481

482482
_getTimePickerConfig(start) {
483483
return {
484-
container: 'inline',
485484
disabled: start ? !this._startDate : !this._endDate,
486485
locale: this._config.locale,
487486
time: start ? this._startDate && new Date(this._startDate) : this._endDate && new Date(this._endDate),
487+
type: 'inline',
488488
variant: 'select'
489489
}
490490
}

js/src/time-picker.js

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import BaseComponent from './base-component.js'
1010
import EventHandler from './dom/event-handler.js'
1111
import Manipulator from './dom/manipulator.js'
1212
import SelectorEngine from './dom/selector-engine.js'
13-
import { defineJQueryPlugin, isRTL } from './util/index.js'
13+
import { defineJQueryPlugin, getElement, isRTL } from './util/index.js'
1414
import {
1515
convert12hTo24h,
1616
convert24hTo12h,
@@ -76,10 +76,10 @@ const SELECTOR_WAS_VALIDATED = 'form.was-validated'
7676
const Default = {
7777
cancelButton: 'Cancel',
7878
cancelButtonClasses: ['btn', 'btn-sm', 'btn-ghost-primary'],
79+
cleaner: true,
7980
confirmButton: 'OK',
8081
confirmButtonClasses: ['btn', 'btn-sm', 'btn-primary'],
81-
cleaner: true,
82-
container: 'dropdown',
82+
container: false,
8383
disabled: false,
8484
footer: true,
8585
hours: null,
@@ -94,17 +94,18 @@ const Default = {
9494
seconds: true,
9595
size: null,
9696
time: null,
97+
type: 'dropdown',
9798
valid: false,
9899
variant: 'roll'
99100
}
100101

101102
const DefaultType = {
102103
cancelButton: '(boolean|string)',
103104
cancelButtonClasses: '(array|string)',
105+
cleaner: 'boolean',
104106
confirmButton: '(boolean|string)',
105107
confirmButtonClasses: '(array|string)',
106-
cleaner: 'boolean',
107-
container: 'string',
108+
container: '(string|element|boolean)',
108109
disabled: 'boolean',
109110
footer: 'boolean',
110111
hours: '(array|function|null)',
@@ -119,6 +120,7 @@ const DefaultType = {
119120
seconds: '(array|boolean|function)',
120121
size: '(string|null)',
121122
time: '(date|string|null)',
123+
type: 'string',
122124
valid: 'boolean',
123125
variant: 'string'
124126
}
@@ -140,6 +142,7 @@ class TimePicker extends BaseComponent {
140142
this._popper = null
141143

142144
this._input = null
145+
this._menu = null
143146
this._timePickerBody = null
144147

145148
this._localizedTimePartials = getLocalizedTimePartials(
@@ -182,6 +185,11 @@ class TimePicker extends BaseComponent {
182185
EventHandler.trigger(this._element, EVENT_SHOW)
183186
this._element.classList.add(CLASS_NAME_SHOW)
184187
this._element.setAttribute('aria-expanded', true)
188+
189+
if (this._config.container) {
190+
this._menu.classList.add(CLASS_NAME_SHOW)
191+
}
192+
185193
EventHandler.trigger(this._element, EVENT_SHOWN)
186194

187195
this._createPopper()
@@ -196,6 +204,11 @@ class TimePicker extends BaseComponent {
196204

197205
this._element.classList.remove(CLASS_NAME_SHOW)
198206
this._element.setAttribute('aria-expanded', 'false')
207+
208+
if (this._config.container) {
209+
this._menu.classList.remove(CLASS_NAME_SHOW)
210+
}
211+
199212
EventHandler.trigger(this._element, EVENT_HIDDEN)
200213
}
201214

@@ -291,7 +304,7 @@ class TimePicker extends BaseComponent {
291304
}
292305
})
293306

294-
if (this._config.container === 'dropdown') {
307+
if (this._config.type === 'dropdown') {
295308
EventHandler.on(this._input.form, EVENT_SUBMIT, () => {
296309
if (this._input.form.classList.contains(CLASS_NAME_WAS_VALIDATED)) {
297310
if (Number.isNaN(Date.parse(`1970-01-01 ${this._input.value}`))) {
@@ -328,7 +341,7 @@ class TimePicker extends BaseComponent {
328341

329342
this._element.classList.toggle(CLASS_NAME_IS_INVALID, this._config.invalid)
330343

331-
if (this._config.container === 'dropdown') {
344+
if (this._config.type === 'dropdown') {
332345
this._element.append(this._createTimePickerInputGroup())
333346

334347
const dropdownEl = document.createElement('div')
@@ -339,11 +352,17 @@ class TimePicker extends BaseComponent {
339352
dropdownEl.append(this._createTimePickerFooter())
340353
}
341354

342-
this._element.append(dropdownEl)
355+
const { container } = this._config
356+
if (container) {
357+
container.append(dropdownEl)
358+
} else {
359+
this._element.append(dropdownEl)
360+
}
361+
343362
this._menu = dropdownEl
344363
}
345364

346-
if (this._config.container === 'inline') {
365+
if (this._config.type === 'inline') {
347366
this._element.append(this._createTimePickerBody())
348367
}
349368
}
@@ -797,8 +816,28 @@ class TimePicker extends BaseComponent {
797816
})
798817
}
799818

800-
// Static
819+
_configAfterMerge(config) {
820+
if (config.container === 'dropdown' || config.container === 'inline') {
821+
config.type = config.container
822+
}
823+
824+
if (config.container === true) {
825+
config.container = document.body
826+
}
827+
828+
if (
829+
typeof config.container === 'object' ||
830+
(typeof config.container === 'string' &&
831+
config.container === 'dropdown' &&
832+
config.container === 'inline')
833+
) {
834+
config.container = getElement(config.container)
835+
}
801836

837+
return config
838+
}
839+
840+
// Static
802841
static timePickerInterface(element, config) {
803842
const data = TimePicker.getOrCreateInstance(element, config)
804843

scss/_time-picker.scss

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
.time-picker {
1+
.time-picker,
2+
*:not(.time-picker) > .time-picker-dropdown {
23
// scss-docs-start time-picker-css-vars
34
--#{$prefix}time-picker-zindex: #{$time-picker-zindex};
45
--#{$prefix}time-picker-font-family: #{$time-picker-font-family};
@@ -189,7 +190,8 @@
189190
@include box-shadow(var(--#{$prefix}time-picker-dropdown-box-shadow));
190191
@include elevation(4);
191192

192-
.time-picker.show & {
193+
.time-picker.show &,
194+
&.show {
193195
display: block;
194196
}
195197
}

0 commit comments

Comments
 (0)