diff --git a/demo/demos.json b/demo/demos.json index 05c39044..23befc5e 100644 --- a/demo/demos.json +++ b/demo/demos.json @@ -53,8 +53,8 @@ }, { "name": "Number Field", - "url": "text-field-number-demos", - "src": "text-field-number-demos.html", + "url": "number-field-demos", + "src": "number-field-demos.html", "meta": { "title": "Vaadin Number Field Examples", "description": "", diff --git a/demo/text-field-number-demos.html b/demo/number-field-demos.html similarity index 62% rename from demo/text-field-number-demos.html rename to demo/number-field-demos.html index a384fdc8..bf17ca7d 100644 --- a/demo/text-field-number-demos.html +++ b/demo/number-field-demos.html @@ -1,4 +1,4 @@ - + diff --git a/src/vaadin-number-field.html b/src/vaadin-number-field.html index 8e46c2a7..9eb5e459 100644 --- a/src/vaadin-number-field.html +++ b/src/vaadin-number-field.html @@ -23,6 +23,14 @@ content: "+"; } + [part="decrease-button"], + [part="increase-button"] { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + /* Hide the native arrow icons */ [part="value"]::-webkit-outer-spin-button, [part="value"]::-webkit-inner-spin-button { @@ -31,7 +39,7 @@ } [part="value"] { - -moz-appearance: textfield; + -moz-appearance: textfield !important; } @@ -114,6 +122,7 @@ ready() { super.ready(); + this.__previousValidInput = this.value || ''; this.focusElement.type = 'number'; this.focusElement.addEventListener('change', this.__onInputChange.bind(this)); } @@ -151,9 +160,9 @@ __add(sign) { const incr = sign * (this.step || 1); // Behave like native number input adjusting to the next exact multiple of step. - this.value = (incr + (incr * Math.floor((parseFloat(this.value || 0) / incr).toFixed(1)))).toFixed(this.__decimals); + this.value = this.focusElement.value = + (incr + (incr * Math.floor((parseFloat(this.value || 0) / incr).toFixed(1)))).toFixed(this.__decimals); this.dispatchEvent(new CustomEvent('change', {bubbles: true})); - this.focusElement.focus(); } _allowed(sign, value, min, max) { @@ -172,9 +181,11 @@ } _valueChanged(newVal, oldVal) { - // native input does not accept certain values, and also converts - // from number to string, so we need synchronize value - this.value = this.focusElement.value; + if (!isNaN(newVal) && !isNaN(parseFloat(newVal).toFixed(this.__decimals))) { + this.value = parseFloat(newVal).toFixed(this.__decimals).toString(); + } else { + this.value = this.focusElement.value = ''; + } super._valueChanged(this.value, oldVal); } @@ -201,6 +212,28 @@ } return super.checkValidity(); } + + _onInput(e) { + const input = this.focusElement; + if (e.data === '-' && (this.__previousValidInput === '-' || !this.__previousValidInput)) { + // Allow minus sign (-) as the first character + this.__previousValidInput = '-'; + } else if (input.validity && input.validity.badInput) { + // Browser deems input value as invalid + if (this.__previousValidInput.length === 2 && this.__previousValidInput.substring(0, 1) === '-') { + // Special case when pressing backspace for example -5 value + this.__previousValidInput = '-'; + } else { + // Don't allow inserted value + input.value = this.__previousValidInput; + } + } else { + // Allow inserted value + this.__previousValidInput = e.target.value; + } + + super._onInput(e); + } } window.customElements.define(NumberFieldElement.is, NumberFieldElement); diff --git a/test/number-field.html b/test/number-field.html index cf52393e..0bae35a9 100644 --- a/test/number-field.html +++ b/test/number-field.html @@ -70,18 +70,22 @@ expect(numberField.value).to.be.equal('1'); }); - it('should focus input and dispatch change event when a button is clicked', () => { + it('should dispatch change event when a button is clicked', () => { const changeSpy = sinon.spy(); numberField.addEventListener('change', changeSpy); - let hasFocus; + increaseButton.click(); + expect(changeSpy.callCount).to.equal(1); + }); + + it('should not focus input when a button is clicked', () => { + let hasFocus = false; input.focus = () => { hasFocus = true; }; increaseButton.click(); - expect(hasFocus).to.be.true; - expect(changeSpy.callCount).to.equal(1); + expect(hasFocus).to.be.false; }); it('should increase value by 0.2 when step is 0.2 and increaseButton is clicked', () => { @@ -94,8 +98,8 @@ }); it('should adjust value to exact step when increaseButton is clicked', () => { - numberField.value = 0.5; numberField.step = 0.2; + numberField.value = 0.5; increaseButton.click(); @@ -144,7 +148,6 @@ expect(numberField.value).to.be.equal('0'); }); - it('should not decrease value when decreaseButton is clicked and min value is reached', () => { numberField.value = 0; numberField.min = 0; @@ -186,8 +189,7 @@ }); describe('input validation', () => { - - it('should be valid with numeric vaules', () => { + it('should be valid with numeric values', () => { expect(numberField.validate()).to.be.true; numberField.value = '1';