From cdd5d27908ce1556d8868daa89005b527cfffbfa Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 30 Oct 2018 20:35:22 +0000 Subject: [PATCH 01/23] Added range slider to --- src/components/inputs/NumberInput.jsx | 44 +++++++++++++++++++++----- src/components/layers/MaxZoomBlock.jsx | 1 + src/components/layers/MinZoomBlock.jsx | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 75ed148..e4fb221 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -68,14 +68,42 @@ class NumberInput extends React.Component { } render() { - return this.changeValue(e.target.value)} - onBlur={this.resetValue} - /> + let rangeEl; + + if( + this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") && + this.props.min !== undefined && this.props.max !== undefined && + this.props.allowRange + ) { + rangeEl = ( + this.changeValue(e.target.value)} + onBlur={this.resetValue} + /> + ); + } + + return
+ {rangeEl} + this.changeValue(e.target.value)} + onBlur={this.resetValue} + /> +
} } diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index b4ab33e..7447593 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -16,6 +16,7 @@ class MaxZoomBlock extends React.Component { data-wd-key="max-zoom" > Date: Thu, 1 Nov 2018 08:28:49 +0000 Subject: [PATCH 02/23] Make range step configurable --- src/components/inputs/NumberInput.jsx | 8 +++++++- src/components/layers/MaxZoomBlock.jsx | 1 + src/components/layers/MinZoomBlock.jsx | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index e4fb221..714ca56 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -8,6 +8,12 @@ class NumberInput extends React.Component { min: PropTypes.number, max: PropTypes.number, onChange: PropTypes.func, + allowRange: PropTypes.bool, + rangeStep: PropTypes.number, + } + + static defaultProps = { + rangeStep: 0.01 } constructor(props) { @@ -80,7 +86,7 @@ class NumberInput extends React.Component { style={{width: "calc(100% - 4em)", flexShrink: "0"}} key="range" type="range" - step="0.01" + step={this.props.rangeStep} max={this.props.max} min={this.props.min} spellCheck="false" diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index 7447593..f0683fd 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -17,6 +17,7 @@ class MaxZoomBlock extends React.Component { > Date: Thu, 1 Nov 2018 18:28:58 +0000 Subject: [PATCH 03/23] Changed min/max zoom range step from 0.1 -> 1 --- src/components/layers/MaxZoomBlock.jsx | 2 +- src/components/layers/MinZoomBlock.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index f0683fd..6183d2e 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -17,7 +17,7 @@ class MaxZoomBlock extends React.Component { > Date: Fri, 2 Nov 2018 08:28:51 +0000 Subject: [PATCH 04/23] Fix to allow high precision on text input and integer on range. --- src/components/inputs/NumberInput.jsx | 39 ++++++++++++++++++--------- src/styles/_input.scss | 10 +++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 714ca56..3371e44 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -23,18 +23,13 @@ class NumberInput extends React.Component { } } - static getDerivedStateFromProps(props, state) { - return { - value: props.value - }; - } - changeValue(newValue) { const value = parseFloat(newValue) const hasChanged = this.state.value !== value if(this.isValid(value) && hasChanged) { this.props.onChange(value) + this.setState({ value: value }) } else { this.setState({ value: newValue }) } @@ -73,6 +68,27 @@ class NumberInput extends React.Component { } } + onChangeRange = (e) => { + const val = parseFloat(rawValue, 10); + const step = this.props.rangeStep; + let out = val; + + if(step) { + // Can't do this with the range step attribute else we won't be able to set a high precision value via the text input. + const snap = val % step; + + // Round up/down to step + if (snap < step/2) { + out = val - snap; + } + else { + out = val + (step - snap); + }; + } + + this.changeValue(out); + } + render() { let rangeEl; @@ -83,22 +99,21 @@ class NumberInput extends React.Component { ) { rangeEl = ( this.changeValue(e.target.value)} + value={this.state.value} + onChange={this.onChangeRange} onBlur={this.resetValue} /> ); } - return
+ return
{rangeEl} Date: Fri, 2 Nov 2018 08:54:20 +0000 Subject: [PATCH 05/23] Fixed typo --- src/components/inputs/NumberInput.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 3371e44..929bbdf 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -69,7 +69,7 @@ class NumberInput extends React.Component { } onChangeRange = (e) => { - const val = parseFloat(rawValue, 10); + const val = parseFloat(e.target.value, 10); const step = this.props.rangeStep; let out = val; From 5053058c328001766703afe886d33952641aea08 Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 20 May 2019 11:21:23 +0100 Subject: [PATCH 06/23] Fixed default values for range slider. --- src/components/inputs/NumberInput.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 5c332ad..742a1cf 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -106,6 +106,8 @@ class NumberInput extends React.Component { this.props.min !== undefined && this.props.max !== undefined && this.props.allowRange ) { + const value = this.props.value === undefined ? this.props.default : this.props.value; + rangeEl = ( From 15cdfbc9805d0ba5287cb92b572b735060a3ca82 Mon Sep 17 00:00:00 2001 From: orangemug Date: Mon, 20 May 2019 11:28:27 +0100 Subject: [PATCH 07/23] Changed default of step 0.01 -> 1 --- src/components/inputs/NumberInput.jsx | 2 +- src/components/layers/MaxZoomBlock.jsx | 1 - src/components/layers/MinZoomBlock.jsx | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 742a1cf..0d0e488 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -13,7 +13,7 @@ class NumberInput extends React.Component { } static defaultProps = { - rangeStep: 0.01 + rangeStep: 1 } constructor(props) { diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index 6183d2e..7447593 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -17,7 +17,6 @@ class MaxZoomBlock extends React.Component { > Date: Tue, 21 May 2019 18:42:19 +0100 Subject: [PATCH 08/23] Fixes for firefox, this makes the range input only update on pointerup --- src/components/inputs/NumberInput.jsx | 82 ++++++++++++++++++--------- src/styles/_input.scss | 5 ++ 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 0d0e488..32e210b 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -21,26 +21,34 @@ class NumberInput extends React.Component { this.state = { editing: false, value: props.value, + dirtyValue: props.value, } } static getDerivedStateFromProps(props, state) { if (!state.editing) { return { - value: props.value + value: props.value, + dirtyValue: props.value, }; } + else { + return null; + } } changeValue(newValue) { this.setState({editing: true}); const value = parseFloat(newValue) - const hasChanged = this.state.value !== value + const hasChanged = this.state.value !== value; if(this.isValid(value) && hasChanged) { this.props.onChange(value) } - this.setState({ value: newValue }) + this.setState({ + value: newValue, + dirtyValue: newValue, + }) } isValid(v) { @@ -78,37 +86,36 @@ class NumberInput extends React.Component { } onChangeRange = (e) => { - const val = parseFloat(e.target.value, 10); + const value = parseFloat(e.target.value, 10); const step = this.props.rangeStep; - let out = val; + let dirtyValue = value; if(step) { // Can't do this with the range step attribute else we won't be able to set a high precision value via the text input. - const snap = val % step; + const snap = value % step; // Round up/down to step if (snap < step/2) { - out = val - snap; + dirtyValue = value - snap; } else { - out = val + (step - snap); + dirtyValue = value + (step - snap); }; } - this.changeValue(out); + this.setState({editing: true, value, dirtyValue}); } render() { - let rangeEl; - if( this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") && this.props.min !== undefined && this.props.max !== undefined && this.props.allowRange ) { - const value = this.props.value === undefined ? this.props.default : this.props.value; + const value = this.state.value === undefined ? this.props.default : this.state.value; + const rangeValue = Number.isNaN(parseFloat(value, 10)) ? this.props.default : value; - rangeEl = ( + return
{ + const {dirtyValue} = this.state; + const hasChanged = this.state.props !== dirtyValue + if(this.isValid(dirtyValue) && hasChanged) { + this.setState({editing: false}, () => { + this.props.onChange(dirtyValue); + }); + } + }} + /> + { + this.changeValue(e.target.value) + }} onBlur={this.resetValue} /> - ); +
+ } + else { + return
+ this.changeValue(e.target.value)} + onBlur={this.resetValue} + /> +
} - - return
- {rangeEl} - this.changeValue(e.target.value)} - onBlur={this.resetValue} - /> -
} } diff --git a/src/styles/_input.scss b/src/styles/_input.scss index 7d1f0cc..066a97b 100644 --- a/src/styles/_input.scss +++ b/src/styles/_input.scss @@ -183,3 +183,8 @@ margin-bottom: $margin-3; } } + +.maputnik-input-block-content { + position: relative; + overflow: hidden; +} From 911549aca33c95e3e9827d1f29ad4390e5a00ea3 Mon Sep 17 00:00:00 2001 From: orangemug Date: Tue, 21 May 2019 18:54:09 +0100 Subject: [PATCH 09/23] Moved data-wd-key onto element --- src/components/inputs/NumberInput.jsx | 10 ++++++++++ src/components/layers/MaxZoomBlock.jsx | 5 ++--- src/components/layers/MinZoomBlock.jsx | 5 ++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 32e210b..a93db93 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -10,6 +10,7 @@ class NumberInput extends React.Component { onChange: PropTypes.func, allowRange: PropTypes.bool, rangeStep: PropTypes.number, + wdKey: PropTypes.string, } static defaultProps = { @@ -107,6 +108,13 @@ class NumberInput extends React.Component { } render() { + let wdProps = {}; + if (this.props.wdKey) { + wdProps = { + "data-wd-key": this.props.wdKey + }; + } + if( this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") && this.props.min !== undefined && this.props.max !== undefined && @@ -146,6 +154,7 @@ class NumberInput extends React.Component { this.changeValue(e.target.value) }} onBlur={this.resetValue} + {...wdProps} />
} @@ -159,6 +168,7 @@ class NumberInput extends React.Component { value={this.state.value} onChange={e => this.changeValue(e.target.value)} onBlur={this.resetValue} + {...wdProps} />
} diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index 7447593..99924aa 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -12,10 +12,9 @@ class MaxZoomBlock extends React.Component { } render() { - return + return + return Date: Tue, 21 May 2019 19:07:28 +0100 Subject: [PATCH 10/23] Moved back to data-wd-key approach and fixed tests --- src/components/inputs/NumberInput.jsx | 11 ++--------- src/components/layers/MaxZoomBlock.jsx | 5 +++-- src/components/layers/MinZoomBlock.jsx | 5 +++-- test/functional/layers/index.js | 4 ++-- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index a93db93..58b0866 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -108,13 +108,6 @@ class NumberInput extends React.Component { } render() { - let wdProps = {}; - if (this.props.wdKey) { - wdProps = { - "data-wd-key": this.props.wdKey - }; - } - if( this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") && this.props.min !== undefined && this.props.max !== undefined && @@ -146,6 +139,7 @@ class NumberInput extends React.Component { /> } @@ -162,13 +155,13 @@ class NumberInput extends React.Component { return
this.changeValue(e.target.value)} onBlur={this.resetValue} - {...wdProps} />
} diff --git a/src/components/layers/MaxZoomBlock.jsx b/src/components/layers/MaxZoomBlock.jsx index 99924aa..7447593 100644 --- a/src/components/layers/MaxZoomBlock.jsx +++ b/src/components/layers/MaxZoomBlock.jsx @@ -12,9 +12,10 @@ class MaxZoomBlock extends React.Component { } render() { - return + return + return Date: Sat, 26 Oct 2019 17:41:56 +0100 Subject: [PATCH 11/23] Removed left over conflict markers and set default. --- src/components/inputs/NumberInput.jsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 383e875..890ea49 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -113,7 +113,6 @@ class NumberInput extends React.Component { } render() { -<<<<<<< HEAD if( this.props.hasOwnProperty("min") && this.props.hasOwnProperty("max") && this.props.min !== undefined && this.props.max !== undefined && @@ -149,7 +148,7 @@ class NumberInput extends React.Component { spellCheck="false" className="maputnik-number" placeholder={this.props.default} - value={this.state.dirtyValue} + value={this.state.dirtyValue === undefined ? "" : this.state.dirtyValue} onChange={e => { this.changeValue(e.target.value) }} From d61d0a5795b3c16ac654b65d718de7eb14510c26 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sat, 26 Oct 2019 18:09:07 +0100 Subject: [PATCH 12/23] Fix test for range slider. --- test/functional/layers/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/functional/layers/index.js b/test/functional/layers/index.js index 7665bc1..1186e41 100644 --- a/test/functional/layers/index.js +++ b/test/functional/layers/index.js @@ -200,7 +200,7 @@ describe("layers", function() { const elem = $(wd.$("layer-list-item:background:"+bgId)); elem.click(); - browser.setValueSafe(wd.$("min-zoom", "input"), 1) + browser.setValueSafe(wd.$("min-zoom", 'input[type="text"]'), 1) const elem2 = $(wd.$("layer-editor.layer-id", "input")); elem2.click(); @@ -232,7 +232,7 @@ describe("layers", function() { const elem = $(wd.$("layer-list-item:background:"+bgId)); elem.click(); - browser.setValueSafe(wd.$("max-zoom", "input"), 1) + browser.setValueSafe(wd.$("max-zoom", 'input[type="text"]'), 1) const elem2 = $(wd.$("layer-editor.layer-id", "input")); elem2.click(); From cd162309a82dc3ff92bd216154519ba80f8931cc Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 27 Oct 2019 10:15:11 +0000 Subject: [PATCH 13/23] Added hopeful fix + logging. --- src/components/inputs/NumberInput.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 890ea49..ea1fba2 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -92,6 +92,7 @@ class NumberInput extends React.Component { } onChangeRange = (e) => { + console.log(">> onChangeRange"); const value = parseFloat(e.target.value, 10); const step = this.props.rangeStep; let dirtyValue = value; @@ -131,8 +132,9 @@ class NumberInput extends React.Component { step="any" spellCheck="false" value={rangeValue} - onChange={this.onChangeRange} + onInput={this.onChangeRange} onPointerUp={() => { + console.log(">> onPointerUp"); const {dirtyValue} = this.state; const hasChanged = this.state.props !== dirtyValue if(this.isValid(dirtyValue) && hasChanged) { From 5aa0b4e7d9cff57c9c22f82a937fadb5e74a5170 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 27 Oct 2019 11:01:33 +0000 Subject: [PATCH 14/23] More logging additional attempt at fixes. --- src/components/inputs/NumberInput.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index ea1fba2..ab5ef25 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -93,6 +93,11 @@ class NumberInput extends React.Component { onChangeRange = (e) => { console.log(">> onChangeRange"); + if (this._cancelNextChangeEvent) { + console.log("onChangeRange:cancel"); + this._cancelNextChangeEvent = false; + return; + } const value = parseFloat(e.target.value, 10); const step = this.props.rangeStep; let dirtyValue = value; @@ -133,7 +138,12 @@ class NumberInput extends React.Component { spellCheck="false" value={rangeValue} onInput={this.onChangeRange} + onMouseUp={() => console.log("mouseup")} + onPointerDown={() => { + this._cancelNextChangeEvent = false; + }} onPointerUp={() => { + this._cancelNextChangeEvent = true; console.log(">> onPointerUp"); const {dirtyValue} = this.state; const hasChanged = this.state.props !== dirtyValue From 88841b56e784beea2394cda94f3422906fe8e08c Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 27 Oct 2019 15:56:22 +0000 Subject: [PATCH 15/23] Added another fix attempt and yet more logging. --- src/components/inputs/NumberInput.jsx | 28 +++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index ab5ef25..e3262fb 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -1,6 +1,8 @@ import React from 'react' import PropTypes from 'prop-types' +let IDX = 0; + class NumberInput extends React.Component { static propTypes = { value: PropTypes.number, @@ -21,6 +23,7 @@ class NumberInput extends React.Component { constructor(props) { super(props) this.state = { + uuid: IDX++, editing: false, value: props.value, dirtyValue: props.value, @@ -29,6 +32,7 @@ class NumberInput extends React.Component { static getDerivedStateFromProps(props, state) { if (!state.editing) { + console.log("getDerivedStateFromProps[%s]", state.uuid, props.value); return { value: props.value, dirtyValue: props.value, @@ -38,13 +42,14 @@ class NumberInput extends React.Component { } changeValue(newValue) { - this.setState({editing: true}); const value = (newValue === "" || newValue === undefined) ? undefined : parseFloat(newValue); - const hasChanged = this.state.value !== value; + const hasChanged = this.props.value !== value; + console.log("changeValue[%s]->hasChanged", this.state.uuid, value, this.isValid(value), this.props.value, "!==", value) if(this.isValid(value) && hasChanged) { + console.log("changeValue[%s]->onChange", this.state.uuid, value); this.props.onChange(value) } this.setState({ @@ -92,9 +97,9 @@ class NumberInput extends React.Component { } onChangeRange = (e) => { - console.log(">> onChangeRange"); + console.log("onChangeRange[%s]", this.state.uuid); if (this._cancelNextChangeEvent) { - console.log("onChangeRange:cancel"); + console.log("onChangeRange[%s]:cancel", this.state.uuid); this._cancelNextChangeEvent = false; return; } @@ -126,6 +131,7 @@ class NumberInput extends React.Component { ) { const value = this.state.value === undefined ? this.props.default : this.state.value; const rangeValue = Number.isNaN(parseFloat(value, 10)) ? this.props.default : value; + console.log("render[%s]", this.state.uuid, value, rangeValue); return
{ this._cancelNextChangeEvent = false; }} + onBlur={() => { + console.log("onBlur[%s]", this.state.uuid); + this.changeValue(this.state.dirtyValue); + }} onPointerUp={() => { + console.log("onPointerUp[%s]", this.state.uuid); this._cancelNextChangeEvent = true; - console.log(">> onPointerUp"); - const {dirtyValue} = this.state; - const hasChanged = this.state.props !== dirtyValue - if(this.isValid(dirtyValue) && hasChanged) { - this.setState({editing: false}, () => { - this.props.onChange(dirtyValue); - }); - } + this.changeValue(this.state.dirtyValue); }} /> Date: Sun, 27 Oct 2019 18:15:54 +0000 Subject: [PATCH 16/23] Add even more logging. --- src/components/inputs/NumberInput.jsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index e3262fb..02cfca5 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -31,14 +31,14 @@ class NumberInput extends React.Component { } static getDerivedStateFromProps(props, state) { + console.log("getDerivedStateFromProps[%s]", state.uuid, props.value, state.value); if (!state.editing) { - console.log("getDerivedStateFromProps[%s]", state.uuid, props.value); return { value: props.value, dirtyValue: props.value, }; } - return {}; + return null; } changeValue(newValue) { @@ -166,6 +166,7 @@ class NumberInput extends React.Component { placeholder={this.props.default} value={this.state.dirtyValue === undefined ? "" : this.state.dirtyValue} onChange={e => { + console.log("input.text->onChange[%s]", this.state.uuid, e.target.value); this.changeValue(e.target.value) }} onBlur={this.resetValue} From d886b14d098411c03a3378bd93d009726b27ba1d Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 07:15:50 +0000 Subject: [PATCH 17/23] Fix to set "editing: false" in blur/pointerup --- src/components/inputs/NumberInput.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 02cfca5..1f7063b 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -150,11 +150,13 @@ class NumberInput extends React.Component { }} onBlur={() => { console.log("onBlur[%s]", this.state.uuid); + this.setState({editing: false}); this.changeValue(this.state.dirtyValue); }} onPointerUp={() => { console.log("onPointerUp[%s]", this.state.uuid); this._cancelNextChangeEvent = true; + this.setState({editing: false}); this.changeValue(this.state.dirtyValue); }} /> From c88f9ab5dc4490deb86c058e44e0b2e9ed862b17 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 07:37:49 +0000 Subject: [PATCH 18/23] Believed fix for race condition in setting dirtyValue --- src/components/inputs/NumberInput.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 1f7063b..ff972ae 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -35,7 +35,6 @@ class NumberInput extends React.Component { if (!state.editing) { return { value: props.value, - dirtyValue: props.value, }; } return null; From 655877f67e5dc579da2fcf19e6d12201f8df91bf Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 10:30:08 +0000 Subject: [PATCH 19/23] Fixed another bug with change events for and added range input keyboard support. Remove logging as react props/state is enough for debugging. --- src/components/inputs/NumberInput.jsx | 63 ++++++++++++++------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index ff972ae..cd497ca 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -31,7 +31,6 @@ class NumberInput extends React.Component { } static getDerivedStateFromProps(props, state) { - console.log("getDerivedStateFromProps[%s]", state.uuid, props.value, state.value); if (!state.editing) { return { value: props.value, @@ -46,9 +45,7 @@ class NumberInput extends React.Component { parseFloat(newValue); const hasChanged = this.props.value !== value; - console.log("changeValue[%s]->hasChanged", this.state.uuid, value, this.isValid(value), this.props.value, "!==", value) if(this.isValid(value) && hasChanged) { - console.log("changeValue[%s]->onChange", this.state.uuid, value); this.props.onChange(value) } this.setState({ @@ -96,13 +93,7 @@ class NumberInput extends React.Component { } onChangeRange = (e) => { - console.log("onChangeRange[%s]", this.state.uuid); - if (this._cancelNextChangeEvent) { - console.log("onChangeRange[%s]:cancel", this.state.uuid); - this._cancelNextChangeEvent = false; - return; - } - const value = parseFloat(e.target.value, 10); + let value = parseFloat(e.target.value, 10); const step = this.props.rangeStep; let dirtyValue = value; @@ -111,15 +102,35 @@ class NumberInput extends React.Component { const snap = value % step; // Round up/down to step - if (snap < step/2) { - dirtyValue = value - snap; + if (this._keyboardEvent) { + // If it's keyboard event we might get a low positive/negative value, + // for example we might go from 13 to 13.23, however because we know + // that came from a keyboard event we always want to increase by a + // single step value. + if (value < this.state.value) { + value = value - snap; + } + else { + value = value - snap + snap; + } } else { - dirtyValue = value + (step - snap); - }; + if (snap < step/2) { + value = value - snap; + } + else { + value = value + (step - snap); + }; + } } + this._keyboardEvent = false; + + // Clamp between min/max + value = Math.max(this.props.min, Math.min(this.props.max, value)); + this.setState({editing: true, value, dirtyValue}); + this.props.onChange(value); } render() { @@ -130,7 +141,6 @@ class NumberInput extends React.Component { ) { const value = this.state.value === undefined ? this.props.default : this.state.value; const rangeValue = Number.isNaN(parseFloat(value, 10)) ? this.props.default : value; - console.log("render[%s]", this.state.uuid, value, rangeValue); return
console.log("mouseup")} - onPointerDown={() => { - this._cancelNextChangeEvent = false; + aria-hidden="true" + onChange={this.onChangeRange} + onKeyDown={() => { + this._keyboardEvent = true; }} onBlur={() => { - console.log("onBlur[%s]", this.state.uuid); this.setState({editing: false}); - this.changeValue(this.state.dirtyValue); - }} - onPointerUp={() => { - console.log("onPointerUp[%s]", this.state.uuid); - this._cancelNextChangeEvent = true; - this.setState({editing: false}); - this.changeValue(this.state.dirtyValue); }} /> { - console.log("input.text->onChange[%s]", this.state.uuid, e.target.value); - this.changeValue(e.target.value) + if (!this.state.editing) { + this.changeValue(e.target.value); + } }} onBlur={this.resetValue} /> From 2ccd1d227eee94255fdec5e4e6f89be6b4273d83 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 11:06:24 +0000 Subject: [PATCH 20/23] rangeValue -> dirtyValue --- src/components/inputs/NumberInput.jsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index cd497ca..5d468fe 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -139,8 +139,8 @@ class NumberInput extends React.Component { this.props.min !== undefined && this.props.max !== undefined && this.props.allowRange ) { - const value = this.state.value === undefined ? this.props.default : this.state.value; - const rangeValue = Number.isNaN(parseFloat(value, 10)) ? this.props.default : value; + const dirtyValue = this.state.dirtyValue === undefined ? this.props.default : this.state.dirtyValue + const value = this.state.value === undefined ? "" : this.state.value; return
{ @@ -167,7 +167,7 @@ class NumberInput extends React.Component { spellCheck="false" className="maputnik-number" placeholder={this.props.default} - value={this.state.value === undefined ? "" : this.state.value} + value={value} onChange={e => { if (!this.state.editing) { this.changeValue(e.target.value); @@ -178,11 +178,13 @@ class NumberInput extends React.Component {
} else { + const value = this.state.value === undefined ? "" : this.state.value; + return this.changeValue(e.target.value)} onBlur={this.resetValue} required={this.props.required} From 926969b9212a2fe639d4b87138944e69756dd442 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 11:28:03 +0000 Subject: [PATCH 21/23] Always change via step from keyboard. --- src/components/inputs/NumberInput.jsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 5d468fe..b474c3c 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -34,6 +34,7 @@ class NumberInput extends React.Component { if (!state.editing) { return { value: props.value, + dirtyValue: props.value, }; } return null; @@ -107,12 +108,13 @@ class NumberInput extends React.Component { // for example we might go from 13 to 13.23, however because we know // that came from a keyboard event we always want to increase by a // single step value. - if (value < this.state.value) { - value = value - snap; + if (value < this.state.dirtyValue) { + value = this.state.value - step; } else { - value = value - snap + snap; + value = this.state.value + step } + dirtyValue = value; } else { if (snap < step/2) { From 0726a494be8232c616a7baea654f82be5ae574b9 Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 11:41:37 +0000 Subject: [PATCH 22/23] Only set dirtyValue on valid change. --- src/components/inputs/NumberInput.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index b474c3c..093eacd 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -48,10 +48,13 @@ class NumberInput extends React.Component { const hasChanged = this.props.value !== value; if(this.isValid(value) && hasChanged) { this.props.onChange(value) + this.setState({ + dirtyValue: newValue, + }); } + this.setState({ value: newValue, - dirtyValue: newValue, }) } From d5ef412300600ccae15dbb66de3e35ee27a610fe Mon Sep 17 00:00:00 2001 From: orangemug Date: Sun, 19 Jan 2020 11:53:27 +0000 Subject: [PATCH 23/23] Safari fixes. --- src/components/inputs/NumberInput.jsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/components/inputs/NumberInput.jsx b/src/components/inputs/NumberInput.jsx index 093eacd..2be980b 100644 --- a/src/components/inputs/NumberInput.jsx +++ b/src/components/inputs/NumberInput.jsx @@ -134,7 +134,7 @@ class NumberInput extends React.Component { // Clamp between min/max value = Math.max(this.props.min, Math.min(this.props.max, value)); - this.setState({editing: true, value, dirtyValue}); + this.setState({value, dirtyValue}); this.props.onChange(value); } @@ -162,6 +162,13 @@ class NumberInput extends React.Component { onKeyDown={() => { this._keyboardEvent = true; }} + onPointerDown={() => { + this.setState({editing: true}); + }} + onPointerUp={() => { + // Safari doesn't get onBlur event + this.setState({editing: false}); + }} onBlur={() => { this.setState({editing: false}); }}