Skip to content

Commit ac97824

Browse files
feat(ui5-wheelslider): add cyclic behaviour (#1408)
1 parent 1fe951d commit ac97824

File tree

5 files changed

+96
-14
lines changed

5 files changed

+96
-14
lines changed

packages/main/src/TimePicker.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ const metadata = {
4747
* Defines a formatted time value.
4848
*
4949
* @type {string}
50-
* @defaultvalue ""
50+
* @defaultvalue undefined
5151
* @public
5252
*/
5353
value: {
5454
type: String,
55-
defaultValue: "",
55+
defaultValue: undefined,
5656
},
5757

5858
/**
@@ -286,6 +286,10 @@ class TimePicker extends UI5Element {
286286
this.formatPattern = LocaleData.getInstance(getLocale()).getTimePattern(this.getFormat().oFormatOptions.style);
287287
}
288288

289+
if (this.value === undefined) {
290+
this.value = this.getFormat().format(new Date());
291+
}
292+
289293
this._initHoursFormatParameters();
290294
}
291295

@@ -656,6 +660,10 @@ class TimePicker extends UI5Element {
656660
}
657661
}
658662

663+
_handleWheel(e) {
664+
e.preventDefault();
665+
}
666+
659667
getFormat() {
660668
if (this._isPattern) {
661669
this._oDateFormat = DateFormat.getInstance({

packages/main/src/TimePickerPopover.hbs

+4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
@ui5-afterOpen="{{_respPopover.afterOpen}}"
1010
class="ui5-timepicker-popover"
1111
@keydown="{{_ontimepickerpopoverkeydown}}"
12+
@wheel="{{_handleWheel}}"
1213
>
1314
<div class="{{classes.container}}" @keydown={{_oncontainerkeydown}} tabindex="0" @focusin="{{_onfocuscontainerin}}">
1415
{{#if shouldBuildHoursSlider}}
@@ -17,6 +18,7 @@
1718
._items="{{hoursArray}}"
1819
@click="{{handleSliderClicked}}"
1920
class="ui5-timepicker-wheelslider ui5-timepicker-hours-wheelslider"
21+
cyclic
2022
></ui5-wheelslider>
2123
{{/if}}
2224
{{#if shouldBuildMinutesSlider}}
@@ -25,6 +27,7 @@
2527
._items="{{minutesArray}}"
2628
@click="{{handleSliderClicked}}"
2729
class="ui5-timepicker-wheelslider ui5-timepicker-minutes-wheelslider"
30+
cyclic
2831
></ui5-wheelslider>
2932
{{/if}}
3033
{{#if shouldBuildSecondsSlider}}
@@ -33,6 +36,7 @@
3336
._items="{{secondsArray}}"
3437
@click="{{handleSliderClicked}}"
3538
class="ui5-timepicker-wheelslider ui5-timepicker-seconds-wheelslider"
39+
cyclic
3640
></ui5-wheelslider>
3741
{{/if}}
3842
{{#if shouldBuildPeriodsSlider}}

packages/main/src/WheelSlider.hbs

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@focusin="{{_onfocusin}}"
1212
@focusout="{{_onfocusout}}"
1313
tabindex="0"
14+
@wheel="{{_handleWheel}}"
1415
>
1516
<div class="ui5-wheelslider-header-block">
1617
<div id="{{this._id}}--label" class="ui5-wheelslider-label"> {{label}}</div>
@@ -20,11 +21,11 @@
2021
<div id="{{this._id}}--inner" class="ui5-wheelslider-inner">
2122
<div id="{{this._id}}--selection-frame" class="ui5-wheelslider-selection-frame">
2223
</div>
23-
<div id="{{this._id}}--wrapper" class="ui5-wheelslider-wrapper" @wheel="{{_handleWheel}}">
24+
<div id="{{this._id}}--wrapper" class="ui5-wheelslider-wrapper">
2425
{{#if _expanded}}
2526
<ul id="{{this._id}}--items-list">
26-
{{#each items}}
27-
<li class="ui5-wheelslider-item">{{this}}</li>
27+
{{#each _itemsToShow}}
28+
<li class="ui5-wheelslider-item" data-item-index="{{@index}}">{{this}}</li>
2829
{{/each}}
2930
</ul>
3031
{{else}}

packages/main/src/WheelSlider.js

+77-8
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,23 @@ const metadata = {
6565
},
6666

6767
_items: {
68-
type: Object,
68+
type: String,
69+
multiple: true,
70+
},
71+
72+
_itemsToShow: {
73+
type: String,
74+
multiple: true,
75+
},
76+
77+
/**
78+
* Indicates if the wheelslider has a cyclic behaviour.
79+
* @type {boolean}
80+
* @defaultvalue false
81+
* @public
82+
*/
83+
cyclic: {
84+
type: Boolean,
6985
},
7086
},
7187
slots: /** @lends sap.ui.webcomponents.main.WheelSlider.prototype */ {
@@ -135,9 +151,20 @@ class WheelSlider extends UI5Element {
135151
super();
136152
this._currentElementIndex = 0;
137153
this._itemCellHeight = 0;
154+
this._itemsToShow = [];
138155
}
139156

140157
onBeforeRendering() {
158+
if (!this._expanded && this.cyclic) {
159+
const index = this._currentElementIndex % this._items.length;
160+
this._currentElementIndex = (this._timesMultipliedOnCyclic() / 2) * this._items.length + index;
161+
}
162+
163+
if (!this.value) {
164+
this.value = this._items[0];
165+
}
166+
167+
this._buildItemsToShow();
141168
this._updateItemCellHeight();
142169
}
143170

@@ -154,7 +181,7 @@ class WheelSlider extends UI5Element {
154181
const elements = this.shadowRoot.querySelectorAll(".ui5-wheelslider-item");
155182
for (let i = 0; i < elements.length; i++) {
156183
if (elements[i].textContent === this.value) {
157-
this._selectElement(elements[i]);
184+
this._selectElementByIndex(Number(elements[i].dataset.itemIndex) + this._getCurrentRepetition() * this._items.length);
158185
return true;
159186
}
160187
}
@@ -163,8 +190,23 @@ class WheelSlider extends UI5Element {
163190
}
164191
}
165192

166-
get items() {
167-
return this._items || [];
193+
_timesMultipliedOnCyclic() {
194+
const minElementsInCyclicWheelSlider = 70;
195+
const repetitionCount = Math.round(minElementsInCyclicWheelSlider / this._items.length);
196+
const minRepetitionCount = 3;
197+
198+
return Math.max(minRepetitionCount, repetitionCount);
199+
}
200+
201+
_buildItemsToShow() {
202+
this._itemsToShow = this._items;
203+
if (this.cyclic) {
204+
if (this._itemsToShow.length < this._items.length * this._timesMultipliedOnCyclic()) {
205+
for (let i = 0; i < this._timesMultipliedOnCyclic(); i++) {
206+
this._itemsToShow = this._itemsToShow.concat(this._items);
207+
}
208+
}
209+
}
168210
}
169211

170212
get classes() {
@@ -223,26 +265,53 @@ class WheelSlider extends UI5Element {
223265

224266
_selectElement(element) {
225267
if (element && this._items.indexOf(element.textContent) > -1) {
226-
this._currentElementIndex = this._items.indexOf(element.textContent);
268+
this._currentElementIndex = Number(element.dataset.itemIndex);
227269
this._selectElementByIndex(this._currentElementIndex);
228270
}
229271
}
230272

231-
_selectElementByIndex(index) {
273+
_getCurrentRepetition() {
274+
if (this._currentElementIndex) {
275+
return Math.floor(this._currentElementIndex / this._items.length);
276+
}
277+
278+
return 0;
279+
}
280+
281+
_selectElementByIndex(currentIndex) {
232282
const sliderElement = this.shadowRoot.getElementById(`${this._id}--items-list`);
233-
const itemsCount = this._items.length;
283+
const itemsCount = this._itemsToShow.length;
234284
const itemCellHeight = this._itemCellHeight ? this._itemCellHeight : 2.875;
235285
const offsetStep = isPhone() ? 4 : 2;
286+
let index = currentIndex;
287+
288+
if (this.cyclic) {
289+
index = this.handleArrayBorderReached(index);
290+
}
236291

237292
if (index < itemsCount && index > -1) {
238293
const offsetSelectedElement = offsetStep * itemCellHeight - (index * itemCellHeight);
239294
sliderElement.setAttribute("style", `top:${offsetSelectedElement}rem`);
240-
this.value = this._items[index];
241295
this._currentElementIndex = index;
296+
this.value = this._items[index - (this._getCurrentRepetition() * this._items.length)];
242297
this.fireEvent("valueSelect", { value: this.value });
243298
}
244299
}
245300

301+
handleArrayBorderReached(currentIndex) {
302+
const arrayLength = this._itemsToShow.length;
303+
const maxVisibleElementsOnOneSide = 5;
304+
let index = currentIndex;
305+
306+
if (maxVisibleElementsOnOneSide > index) {
307+
index += this._items.length * 2;
308+
} else if (index > arrayLength - maxVisibleElementsOnOneSide) {
309+
index -= this._items.length * 2;
310+
}
311+
312+
return index;
313+
}
314+
246315
_onArrowDown(e) {
247316
e.preventDefault();
248317
const nextElementIndex = this._currentElementIndex + 1;

packages/main/test/pages/TimePicker.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
</head>
2222
<body style="background-color: var(--sapBackgroundColor);">
2323
<ui5-timepicker id="timepicker" format-pattern="HH:mm:ss"></ui5-timepicker>
24-
<ui5-timepicker id="timepicker2" format-pattern="hh:mm:ss"></ui5-timepicker>
24+
<ui5-timepicker id="timepicker2" format-pattern="hh:mm:ss" value=""></ui5-timepicker>
2525
<ui5-timepicker id="timepicker3" format-pattern="hh:mm:ss a"></ui5-timepicker>
2626
<ui5-timepicker id="timepicker3" format-pattern="HH:mm"></ui5-timepicker>
2727

0 commit comments

Comments
 (0)