Skip to content

Commit

Permalink
feat(ui5-wheelslider): add cyclic behaviour (#1408)
Browse files Browse the repository at this point in the history
  • Loading branch information
tsanislavgatev committed Apr 2, 2020
1 parent 1fe951d commit ac97824
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 14 deletions.
12 changes: 10 additions & 2 deletions packages/main/src/TimePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ const metadata = {
* Defines a formatted time value.
*
* @type {string}
* @defaultvalue ""
* @defaultvalue undefined
* @public
*/
value: {
type: String,
defaultValue: "",
defaultValue: undefined,
},

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

if (this.value === undefined) {
this.value = this.getFormat().format(new Date());
}

this._initHoursFormatParameters();
}

Expand Down Expand Up @@ -656,6 +660,10 @@ class TimePicker extends UI5Element {
}
}

_handleWheel(e) {
e.preventDefault();
}

getFormat() {
if (this._isPattern) {
this._oDateFormat = DateFormat.getInstance({
Expand Down
4 changes: 4 additions & 0 deletions packages/main/src/TimePickerPopover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@ui5-afterOpen="{{_respPopover.afterOpen}}"
class="ui5-timepicker-popover"
@keydown="{{_ontimepickerpopoverkeydown}}"
@wheel="{{_handleWheel}}"
>
<div class="{{classes.container}}" @keydown={{_oncontainerkeydown}} tabindex="0" @focusin="{{_onfocuscontainerin}}">
{{#if shouldBuildHoursSlider}}
Expand All @@ -17,6 +18,7 @@
._items="{{hoursArray}}"
@click="{{handleSliderClicked}}"
class="ui5-timepicker-wheelslider ui5-timepicker-hours-wheelslider"
cyclic
></ui5-wheelslider>
{{/if}}
{{#if shouldBuildMinutesSlider}}
Expand All @@ -25,6 +27,7 @@
._items="{{minutesArray}}"
@click="{{handleSliderClicked}}"
class="ui5-timepicker-wheelslider ui5-timepicker-minutes-wheelslider"
cyclic
></ui5-wheelslider>
{{/if}}
{{#if shouldBuildSecondsSlider}}
Expand All @@ -33,6 +36,7 @@
._items="{{secondsArray}}"
@click="{{handleSliderClicked}}"
class="ui5-timepicker-wheelslider ui5-timepicker-seconds-wheelslider"
cyclic
></ui5-wheelslider>
{{/if}}
{{#if shouldBuildPeriodsSlider}}
Expand Down
7 changes: 4 additions & 3 deletions packages/main/src/WheelSlider.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
@focusin="{{_onfocusin}}"
@focusout="{{_onfocusout}}"
tabindex="0"
@wheel="{{_handleWheel}}"
>
<div class="ui5-wheelslider-header-block">
<div id="{{this._id}}--label" class="ui5-wheelslider-label"> {{label}}</div>
Expand All @@ -20,11 +21,11 @@
<div id="{{this._id}}--inner" class="ui5-wheelslider-inner">
<div id="{{this._id}}--selection-frame" class="ui5-wheelslider-selection-frame">
</div>
<div id="{{this._id}}--wrapper" class="ui5-wheelslider-wrapper" @wheel="{{_handleWheel}}">
<div id="{{this._id}}--wrapper" class="ui5-wheelslider-wrapper">
{{#if _expanded}}
<ul id="{{this._id}}--items-list">
{{#each items}}
<li class="ui5-wheelslider-item">{{this}}</li>
{{#each _itemsToShow}}
<li class="ui5-wheelslider-item" data-item-index="{{@index}}">{{this}}</li>
{{/each}}
</ul>
{{else}}
Expand Down
85 changes: 77 additions & 8 deletions packages/main/src/WheelSlider.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,23 @@ const metadata = {
},

_items: {
type: Object,
type: String,
multiple: true,
},

_itemsToShow: {
type: String,
multiple: true,
},

/**
* Indicates if the wheelslider has a cyclic behaviour.
* @type {boolean}
* @defaultvalue false
* @public
*/
cyclic: {
type: Boolean,
},
},
slots: /** @lends sap.ui.webcomponents.main.WheelSlider.prototype */ {
Expand Down Expand Up @@ -135,9 +151,20 @@ class WheelSlider extends UI5Element {
super();
this._currentElementIndex = 0;
this._itemCellHeight = 0;
this._itemsToShow = [];
}

onBeforeRendering() {
if (!this._expanded && this.cyclic) {
const index = this._currentElementIndex % this._items.length;
this._currentElementIndex = (this._timesMultipliedOnCyclic() / 2) * this._items.length + index;
}

if (!this.value) {
this.value = this._items[0];
}

this._buildItemsToShow();
this._updateItemCellHeight();
}

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

get items() {
return this._items || [];
_timesMultipliedOnCyclic() {
const minElementsInCyclicWheelSlider = 70;
const repetitionCount = Math.round(minElementsInCyclicWheelSlider / this._items.length);
const minRepetitionCount = 3;

return Math.max(minRepetitionCount, repetitionCount);
}

_buildItemsToShow() {
this._itemsToShow = this._items;
if (this.cyclic) {
if (this._itemsToShow.length < this._items.length * this._timesMultipliedOnCyclic()) {
for (let i = 0; i < this._timesMultipliedOnCyclic(); i++) {
this._itemsToShow = this._itemsToShow.concat(this._items);
}
}
}
}

get classes() {
Expand Down Expand Up @@ -223,26 +265,53 @@ class WheelSlider extends UI5Element {

_selectElement(element) {
if (element && this._items.indexOf(element.textContent) > -1) {
this._currentElementIndex = this._items.indexOf(element.textContent);
this._currentElementIndex = Number(element.dataset.itemIndex);
this._selectElementByIndex(this._currentElementIndex);
}
}

_selectElementByIndex(index) {
_getCurrentRepetition() {
if (this._currentElementIndex) {
return Math.floor(this._currentElementIndex / this._items.length);
}

return 0;
}

_selectElementByIndex(currentIndex) {
const sliderElement = this.shadowRoot.getElementById(`${this._id}--items-list`);
const itemsCount = this._items.length;
const itemsCount = this._itemsToShow.length;
const itemCellHeight = this._itemCellHeight ? this._itemCellHeight : 2.875;
const offsetStep = isPhone() ? 4 : 2;
let index = currentIndex;

if (this.cyclic) {
index = this.handleArrayBorderReached(index);
}

if (index < itemsCount && index > -1) {
const offsetSelectedElement = offsetStep * itemCellHeight - (index * itemCellHeight);
sliderElement.setAttribute("style", `top:${offsetSelectedElement}rem`);
this.value = this._items[index];
this._currentElementIndex = index;
this.value = this._items[index - (this._getCurrentRepetition() * this._items.length)];
this.fireEvent("valueSelect", { value: this.value });
}
}

handleArrayBorderReached(currentIndex) {
const arrayLength = this._itemsToShow.length;
const maxVisibleElementsOnOneSide = 5;
let index = currentIndex;

if (maxVisibleElementsOnOneSide > index) {
index += this._items.length * 2;
} else if (index > arrayLength - maxVisibleElementsOnOneSide) {
index -= this._items.length * 2;
}

return index;
}

_onArrowDown(e) {
e.preventDefault();
const nextElementIndex = this._currentElementIndex + 1;
Expand Down
2 changes: 1 addition & 1 deletion packages/main/test/pages/TimePicker.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</head>
<body style="background-color: var(--sapBackgroundColor);">
<ui5-timepicker id="timepicker" format-pattern="HH:mm:ss"></ui5-timepicker>
<ui5-timepicker id="timepicker2" format-pattern="hh:mm:ss"></ui5-timepicker>
<ui5-timepicker id="timepicker2" format-pattern="hh:mm:ss" value=""></ui5-timepicker>
<ui5-timepicker id="timepicker3" format-pattern="hh:mm:ss a"></ui5-timepicker>
<ui5-timepicker id="timepicker3" format-pattern="HH:mm"></ui5-timepicker>

Expand Down

0 comments on commit ac97824

Please sign in to comment.