Extend paper-slider to fix rounding issue. (#1709)

This commit is contained in:
Jerad Meisner 2018-09-27 01:06:56 -07:00 committed by Paulus Schoutsen
parent 458a7827f9
commit 3961eff372
3 changed files with 38 additions and 7 deletions

View File

@ -0,0 +1,31 @@
import '@polymer/paper-slider';
const PaperSliderClass = customElements.get('paper-slider');
class HaSlider extends PaperSliderClass {
_calcStep(value) {
if (!this.step) {
return parseFloat(value);
}
const numSteps = Math.round((value - this.min) / this.step);
const stepStr = this.step.toString();
const stepPointAt = stepStr.indexOf('.');
if (stepPointAt !== -1) {
/**
* For small values of this.step, if we calculate the step using
* For non-integer values of this.step, if we calculate the step using
* `Math.round(value / step) * step` we may hit a precision point issue
* eg. 0.1 * 0.2 = 0.020000000000000004
* http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
*
* as a work around we can round with the decimal precision of `step`
*/
const precision = 10 ** (stepStr.length - stepPointAt - 1);
return Math.round((numSteps * this.step + this.min) * precision) / precision;
}
return numSteps * this.step + this.min;
}
}
customElements.define('ha-slider', HaSlider);

View File

@ -1,11 +1,11 @@
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '@polymer/paper-input/paper-input.js'; import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-slider/paper-slider.js';
import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js'; import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js'; import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js';
import '../components/hui-generic-entity-row.js'; import '../components/hui-generic-entity-row.js';
import '../../../components/ha-slider';
class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], PolymerElement) { class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], PolymerElement) {
static get template() { static get template() {
@ -44,7 +44,7 @@ class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], Po
<div> <div>
<template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'slider')]]"> <template is="dom-if" if="[[_equals(_stateObj.attributes.mode, 'slider')]]">
<div class="flex"> <div class="flex">
<paper-slider <ha-slider
min="[[_min]]" min="[[_min]]"
max="[[_max]]" max="[[_max]]"
value="{{_value}}" value="{{_value}}"
@ -52,7 +52,7 @@ class HuiInputNumberEntityRow extends mixinBehaviors([IronResizableBehavior], Po
pin pin
on-change="_selectedValueChanged" on-change="_selectedValueChanged"
ignore-bar-touch ignore-bar-touch
></paper-slider> ></ha-slider>
<span class="state">[[_value]] [[_stateObj.attributes.unit_of_measurement]]</span> <span class="state">[[_value]] [[_stateObj.attributes.unit_of_measurement]]</span>
</div> </div>
</template> </template>

View File

@ -1,12 +1,12 @@
import '@polymer/iron-flex-layout/iron-flex-layout-classes.js'; import '@polymer/iron-flex-layout/iron-flex-layout-classes.js';
import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js'; import { IronResizableBehavior } from '@polymer/iron-resizable-behavior/iron-resizable-behavior.js';
import '@polymer/paper-input/paper-input.js'; import '@polymer/paper-input/paper-input.js';
import '@polymer/paper-slider/paper-slider.js';
import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js'; import { mixinBehaviors } from '@polymer/polymer/lib/legacy/class.js';
import { html } from '@polymer/polymer/lib/utils/html-tag.js'; import { html } from '@polymer/polymer/lib/utils/html-tag.js';
import { PolymerElement } from '@polymer/polymer/polymer-element.js'; import { PolymerElement } from '@polymer/polymer/polymer-element.js';
import '../components/entity/state-info.js'; import '../components/entity/state-info.js';
import '../components/ha-slider';
class StateCardInputNumber extends mixinBehaviors([ class StateCardInputNumber extends mixinBehaviors([
IronResizableBehavior IronResizableBehavior
@ -15,7 +15,7 @@ class StateCardInputNumber extends mixinBehaviors([
return html` return html`
<style include="iron-flex iron-flex-alignment"></style> <style include="iron-flex iron-flex-alignment"></style>
<style> <style>
paper-slider { ha-slider {
margin-left: auto; margin-left: auto;
} }
.state { .state {
@ -28,7 +28,7 @@ class StateCardInputNumber extends mixinBehaviors([
.sliderstate { .sliderstate {
min-width: 45px; min-width: 45px;
} }
paper-slider[hidden] { ha-slider[hidden] {
display: none !important; display: none !important;
} }
paper-input { paper-input {
@ -39,7 +39,7 @@ class StateCardInputNumber extends mixinBehaviors([
<div class="horizontal justified layout" id="input_number_card"> <div class="horizontal justified layout" id="input_number_card">
${this.stateInfoTemplate} ${this.stateInfoTemplate}
<paper-slider min="[[min]]" max="[[max]]" value="{{value}}" step="[[step]]" hidden="[[hiddenslider]]" pin="" on-change="selectedValueChanged" on-click="stopPropagation" id="slider" ignore-bar-touch=""> <ha-slider min="[[min]]" max="[[max]]" value="{{value}}" step="[[step]]" hidden="[[hiddenslider]]" pin="" on-change="selectedValueChanged" on-click="stopPropagation" id="slider" ignore-bar-touch="">
</paper-slider> </paper-slider>
<paper-input no-label-float="" auto-validate="" pattern="[0-9]+([\\.][0-9]+)?" step="[[step]]" min="[[min]]" max="[[max]]" value="{{value}}" type="number" on-change="selectedValueChanged" on-click="stopPropagation" hidden="[[hiddenbox]]"> <paper-input no-label-float="" auto-validate="" pattern="[0-9]+([\\.][0-9]+)?" step="[[step]]" min="[[min]]" max="[[max]]" value="{{value}}" type="number" on-change="selectedValueChanged" on-click="stopPropagation" hidden="[[hiddenbox]]">
</paper-input> </paper-input>