Skip to content

Commit

Permalink
Add additional validations and normalizations, refactoring, documenta…
Browse files Browse the repository at this point in the history
…tion

Normalization of the min and max value is introduced. If the min
property is set to be more than the max one they are swapped.

Validation of the step property is improved. If a negative value is
provided it gets converted to its positive equivalent.
Warning are now being display if the step value is 0, a negative number
or not a valid floating number.

The tickmarks property is renamed to showTickmarks.

Some refactoring is performed according to the code reviews.

Added more documentation.
  • Loading branch information
ndeshev committed Nov 11, 2020
1 parent fc51ad5 commit 359db57
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 44 deletions.
38 changes: 32 additions & 6 deletions packages/main/src/RangeSlider.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const metadata = {
managedSlots: true,
properties: /** @lends sap.ui.webcomponents.main.RangeSlider.prototype */ {
/**
* Determines start point of a selection - position of a first handle on the slider.
* Defines start point of a selection - position of a first handle on the slider.
* <br><br>
*
* @type {Float}
Expand All @@ -26,7 +26,7 @@ const metadata = {
defaultValue: 0,
},
/**
* Determines end point of a selection - position of a second handle on the slider.
* Defines end point of a selection - position of a second handle on the slider.
* <br><br>
*
* @type {Float}
Expand All @@ -43,8 +43,36 @@ const metadata = {
/**
* @class
*
* <h3 class="comment-api-title">Overview</h3>
* Represents a numerical interval and two handles (grips) to select a sub-range within it.
*
* <h3 class="comment-api-title">Overview</h3>
* The purpose of the control is to enable visual selection of sub-ranges within a given interval.
*
* <h3>Structure</h3>
* The most important properties of the Range Slider are:
* <ul>
* <li>min - The minimum value of the slider range</li>
* <li>max - The maximum value of the slider range</li>
* <li>value - The current value of the slider</li>
* <li>step - Determines the increments in which the slider will move</li>
* <li>showTooltip - Determines if a tooltip should be displayed above the handle</li>
* <li>tickmarks - Displays a visual divider between the step values</li>
* <li>labelInterval - Labels some or all of the tickmarks with their values.</li>
* </ul>
* <h4>Notes:<h4>
* <ul>
* <li>The right and left handle can be moved individually and their positions could therefore switch.</li>
* <li>The entire range can be moved along the interval.</li>
* </ul>
* <h3>Usage</h3>
* The most common usecase is to select and move sub-ranges on a continuous numerical scale.
*
* <h3>Responsive Behavior</h3>
* You can move the currently selected range by clicking on it and dragging it along the interval.
*
* <h3>ES6 Module Import</h3>
*
* <code>import "@ui5/webcomponents/dist/RangeSlider";</code>
*
*
* @constructor
Expand Down Expand Up @@ -356,9 +384,7 @@ class RangeSlider extends SliderBase {
}

static async onDefine() {
await Promise.all([
fetchI18nBundle("@ui5/webcomponents"),
]);
await fetchI18nBundle("@ui5/webcomponents");
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/main/src/SliderBase.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</div>

{{#if step}}
{{#if tickmarks}}
{{#if showTickmarks}}
<div class="ui5-slider-tickmarks" style="{{styles.tickmarks}}"></div>
{{#if labelInterval}}
<ul class="ui5-slider-labels {{classes.labelContainer}}" style="{{styles.labelContainer}}">
Expand Down
93 changes: 60 additions & 33 deletions packages/main/src/SliderBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import styles from "./generated/themes/SliderBase.css.js";
const metadata = {
properties: /** @lends sap.ui.webcomponents.main.SliderBase.prototype */ {
/**
* Minimum value of the slider
* <br><br>
* Defines the minimum value of the slider
*
* @type {Float}
* @defaultvalue 0
Expand All @@ -26,8 +25,7 @@ const metadata = {
defaultValue: 0,
},
/**
* Maximum value of the slider
* <br><br>
* Defines the maximum value of the slider
*
* @type {Float}
* @defaultvalue 100
Expand All @@ -39,8 +37,7 @@ const metadata = {
},
/**
* Defines the size of the slider's selection intervals. (e.g. min = 0, max = 10, step = 5 would result in possible selection of the values 0, 5, 10).
* If 0 no visible interval between value changes will appear. When negative number, the component fallbacks to its default value.
* <br><br>
* If set to 0 the slider handle movement is disabled. When negative number or value other than a number, the component fallbacks to its default value.
*
* @type {Integer}
* @defaultvalue 1
Expand All @@ -51,32 +48,32 @@ const metadata = {
defaultValue: 1,
},
/**
* Put a label with a value on every N-th step. The step and tickmarks properties must be enabled.
* Displays a label with a value on every N-th step. The step and tickmarks properties must be enabled.
* Example - if the step value is set to 2 and the label interval is also specified to 2 - than every second
* tickmark will be labelled, which means every 4th round value number.
* tickmark will be labelled, which means every 4th value number.
*
* @type {Integer}
* @defaultvalue 1
* @defaultvalue 0
* @public
*/
labelInterval: {
type: Integer,
defaultValue: 0,
},
/**
* Enables tick marks visualization for each step. The step value must not be set to 0.
* Enables tick marks visualization for each step.
* <br><br>
* <b>Note:</b> The step must be a positive number.
*
* @type {boolean}
* @defaultvalue false
* @public
*/
tickmarks: {
showTickmarks: {
type: Boolean,
},
/**
* Enables handle tooltip displaying the current value.
* <br><br>
*
* @type {boolean}
* @defaultvalue false
Expand All @@ -86,8 +83,7 @@ const metadata = {
type: Boolean,
},
/**
* Defines whether the <code>ui5-slider</code> is in disabled state.
* <br><br>
* Defines whether the <code>slider</code> is in disabled state.
*
* @type {boolean}
* @defaultvalue false
Expand Down Expand Up @@ -123,7 +119,7 @@ const metadata = {
type: Node,
},
},
events: /** @lends sap.ui.webcomponents.main.Slider.prototype */ {
events: /** @lends sap.ui.webcomponents.main.SliderBase.prototype */ {
/**
* Fired when the value changes and the user has finished interacting with the slider.
*
Expand Down Expand Up @@ -161,21 +157,14 @@ class SliderBase extends UI5Element {
this._moveHandler = this._handleMove.bind(this);
this._upHandler = this._handleUp.bind(this);

this.TICKMARK_COLOR_MAP = {
sap_fiori_3: "#89919a",
sap_fiori_3_dark: "#89919a",
sap_fiori_3_hcw: "#000000",
sap_fiori_3_hcb: "#ffffff",
sap_belize: "#bfbfbf",
sap_belize_hcw: "#000000",
sap_belize_hcb: "#ffffff",
};

this._stateStorage = {
step: null,
min: null,
max: null,
};

// Stores the label values for the tickmarks
this._labelItems = [];
}

static get metadata() {
Expand All @@ -190,6 +179,18 @@ class SliderBase extends UI5Element {
return styles;
}

static get TICKMARK_COLOR_MAP() {
return {
sap_fiori_3: "#89919a",
sap_fiori_3_dark: "#89919a",
sap_fiori_3_hcw: "#000000",
sap_fiori_3_hcb: "#ffffff",
sap_belize: "#bfbfbf",
sap_belize_hcw: "#000000",
sap_belize_hcb: "#ffffff",
};
}

static get UP_EVENTS() {
return ["mouseup", "pointerup", "touchend"];
}
Expand Down Expand Up @@ -224,6 +225,7 @@ class SliderBase extends UI5Element {
ResizeHandler.deregister(this, this._handleResize);
this.removeEventListener("mouseover", this._mouseOverHandler);
this.removeEventListener("mouseout", this._mouseOutHandler);
this._labelItems = null;
}

onAfterRendering() {
Expand Down Expand Up @@ -269,7 +271,7 @@ class SliderBase extends UI5Element {
* @private
*/
_handleResize() {
if (!this.tickmarks) {
if (!this.showTickmarks) {
return;
}

Expand All @@ -278,9 +280,7 @@ class SliderBase extends UI5Element {

// Convert the string represented calculation expression to a normal one
// Check the distance in pixels exist between every tickmark
const tickmarksAmountStrCalc = this._tickmarksAmount.split("/");
const tickmarksAmount = tickmarksAmountStrCalc[0] / tickmarksAmountStrCalc[1];
const spaceBetweenTickmarks = this.getBoundingClientRect().width / tickmarksAmount;
const spaceBetweenTickmarks = this._spaceBetweenTickmarks();

// If the pixels between the tickmarks are less than 8 only the first and the last one should be visible
// In such case the labels must correspond to the tickmarks, only the first and the last one should exist.
Expand Down Expand Up @@ -451,6 +451,7 @@ class SliderBase extends UI5Element {

// Recalculate the tickmarks and labels and update the stored state.
if (this.isPropertyUpdated("min", "max")) {
this._normalizeMinMaxValues(this.min, this.max);
this._drawDefaultTickmarks(this.step, this.max, this.min);
this.storePropertyState("min", "max");
}
Expand Down Expand Up @@ -524,13 +525,20 @@ class SliderBase extends UI5Element {
return this.effectiveDir === "rtl" ? "right" : "left";
}

_normalizeMinMaxValues(min, max) {
if (min > max) {
this.min = max;
this.max = min;
}
}

/**
* Calculates and draws the tickmarks with a CSS gradient style
*
* @private
*/
_drawDefaultTickmarks(step, max, min) {
if (!this.tickmarks || !this.step) {
if (!this.showTickmarks || !this.step) {
return;
}

Expand All @@ -544,7 +552,7 @@ class SliderBase extends UI5Element {
// There is a CSS bug with the 'currentcolor' value of a CSS gradient that does not
// respect the variable for more than one theme. It has to be set here for now.
const currentTheme = getTheme();
const currentColor = this.TICKMARK_COLOR_MAP[currentTheme];
const currentColor = SliderBase.TICKMARK_COLOR_MAP[currentTheme];

this._tickmarksAmount = `${maxStr - minStr} / ${stepStr}`;
this._hiddenTickmarks = false;
Expand Down Expand Up @@ -597,6 +605,18 @@ class SliderBase extends UI5Element {
}
}

/**
* Calculates space between tickmarks
*
* @private
*/
_spaceBetweenTickmarks() {
const tickmarksAmountStrCalc = this._tickmarksAmount.split("/");
const tickmarksAmount = tickmarksAmountStrCalc[0] / tickmarksAmountStrCalc[1];

return this.getBoundingClientRect().width / tickmarksAmount;
}

/**
* Normalizes a new <code>step</code> property value.
* If tickmarks are enabled recreates them according to it.
Expand All @@ -605,14 +625,21 @@ class SliderBase extends UI5Element {
*/
_setStep(step) {
if (step === 0) {
console.warn("The 'step' property must be a positive float number");
return;
}

if (typeof step !== "number" || step < 0 || Number.isNaN(step)) {
if (step < 0) {
console.warn("The 'step' property must be a positive float number. The provided negative number has been converted to its positve equivalent");
step = Math.abs(step);
}

if (typeof step !== "number" || Number.isNaN(step)) {
console.warn("The 'step' property must be a positive float number. It has been set to its default value of 1");
step = 1;
}

if (this.tickmarks && !this._initialRendering) {
if (!this._initialRendering) {
this._drawDefaultTickmarks(step, this.max, this.min);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/main/test/pages/RangeSlider.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@
<body style="background-color: var(--sapBackgroundColor);">
<section class="group">
<h2>Range Slider with steps and tickmarks</h2>
<ui5-range-slider id="range-slider-tickmarks" min="0" max="33" step="1" end-value="11" tickmarks label-interval="1"></ui5-range-slider>
<ui5-range-slider id="range-slider-tickmarks" min="0" max="33" step="1" end-value="11" show-tickmarks label-interval="1"></ui5-range-slider>

<h2>Inactive Range Slider with tooltips and no steps (no interaction is possible)</h2>
<ui5-range-slider id="range-slider-smooth" min="0" max="30" step="0" start-value="3" end-value="13" show-tooltip></ui5-range-slider>

<h2 style="text-align: center;">Range Slider with steps, tooltips, tickmarks and labels</h2>
<ui5-range-slider id="range-slider-tickmarks-tooltips" min="0" max="44" step="2" start-value="2" end-value="12" show-tooltip label-interval="2" tickmarks style="width: 60%; margin-left: 20%; margin-top: 50px;"></ui5-range-slider>
<ui5-range-slider id="range-slider-tickmarks-tooltips" min="0" max="44" step="2" start-value="2" end-value="12" show-tooltip label-interval="2" show-tickmarks style="width: 60%; margin-left: 20%; margin-top: 50px;"></ui5-range-slider>
<h2 style="text-align: center;">Range Slider with small steps</h2>
<ui5-range-slider id="range-slider-small-step-tooltips" min="0" max="44" step="0.000001" start-value="2" end-value="12" show-tooltip style="width: 60%; margin-left: 20%; margin-top: 50px;"></ui5-range-slider>
</section>
Expand Down
4 changes: 2 additions & 2 deletions packages/main/test/samples/RangeSlider.sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ <h3>Range Slider with Tooltips</h3>
<section>
<h3>Range Slider with Tooltips, Tickmarks and Labels</h3>
<div class="snippet">
<ui5-range-slider class="samples-margin" min="0" max="112" step="2" start-value="4" end-value="12" show-tooltip label-interval="2" tickmarks></ui5-range-slider>
<ui5-range-slider class="samples-margin" min="0" max="112" step="2" start-value="4" end-value="12" show-tooltip label-interval="2" show-tckmarks></ui5-range-slider>
</div>
<pre class="prettyprint lang-html"><xmp>
<ui5-range-slider min="0" max="112" step="2" start-value="4" end-value="12" show-tooltip label-interval="2" tickmarks></ui5-range-slider>
<ui5-range-slider min="0" max="112" step="2" start-value="4" end-value="12" show-tooltip label-interval="2" show-tckmarks></ui5-range-slider>
</xmp></pre>
</section>

Expand Down

0 comments on commit 359db57

Please sign in to comment.