From dbd15d7823f0017c8b981a889061c8efeaa48e36 Mon Sep 17 00:00:00 2001 From: Konstantin Vyatkin Date: Mon, 28 Oct 2019 15:27:10 -0400 Subject: [PATCH] don't calculate pixel width (#694) --- src/scripts/components/input.js | 30 +++---------- src/scripts/components/input.test.js | 64 ++++++---------------------- src/scripts/lib/utils.js | 48 --------------------- 3 files changed, 18 insertions(+), 124 deletions(-) diff --git a/src/scripts/components/input.js b/src/scripts/components/input.js index f2c97be..d7c2968 100644 --- a/src/scripts/components/input.js +++ b/src/scripts/components/input.js @@ -1,4 +1,4 @@ -import { calcWidthOfInput, sanitise } from '../lib/utils'; +import { sanitise } from '../lib/utils'; export default class Input { constructor({ element, type, classNames, placeholderValue }) { @@ -89,30 +89,12 @@ export default class Input { /** * Set the correct input width based on placeholder * value or input value - * @return */ - setWidth(enforceWidth) { - const callback = width => { - this.element.style.width = width; - }; - - if (this._placeholderValue) { - // If there is a placeholder, we only want to set the width of the input when it is a greater - // length than 75% of the placeholder. This stops the input jumping around. - const valueHasDesiredLength = - this.element.value.length >= this._placeholderValue.length / 1.25; - - if ((this.element.value && valueHasDesiredLength) || enforceWidth) { - this.calcWidth(callback); - } - } else { - // If there is no placeholder, resize input to contents - this.calcWidth(callback); - } - } - - calcWidth(callback) { - return calcWidthOfInput(this.element, callback); + setWidth() { + // Resize input to contents or placeholder + const { style, value, placeholder } = this.element; + style.minWidth = `${placeholder.length + 1}ch`; + style.width = `${value.length + 1}ch`; } setActiveDescendant(activeDescendantID) { diff --git a/src/scripts/components/input.test.js b/src/scripts/components/input.test.js index 45172fc..2065335 100644 --- a/src/scripts/components/input.test.js +++ b/src/scripts/components/input.test.js @@ -264,61 +264,21 @@ describe('components/input', () => { }); }); + /** + * Blocked by lack of ch support in JSDOM + * @see {@link https://github.com/jsdom/cssstyle/pull/107} + * describe('setWidth', () => { - let calcWidthStub; - const inputWidth = '200px'; - - beforeEach(() => { - calcWidthStub = stub(instance, 'calcWidth').callsArgWith(0, inputWidth); - }); - - afterEach(() => { - calcWidthStub.restore(); - }); - - describe('with a placeholder', () => { - describe('when value length is greater or equal to 75% of the placeholder length', () => { - it('sets the width of the element based on input value', () => { - instance._placeholderValue = 'This is a test'; - instance.element.value = 'This is a test'; - expect(instance.element.style.width).to.not.equal(inputWidth); - instance.setWidth(); - expect(calcWidthStub.callCount).to.equal(1); - expect(instance.element.style.width).to.equal(inputWidth); - }); - }); - - describe('when width is enforced', () => { - it('sets the width of the element based on input value', () => { - instance._placeholderValue = 'This is a test'; - instance.element.value = ''; - expect(instance.element.style.width).to.not.equal(inputWidth); - instance.setWidth(true); - expect(calcWidthStub.callCount).to.equal(1); - expect(instance.element.style.width).to.equal(inputWidth); - }); - }); - - describe('when value length is less than 75% of the placeholder length', () => { - it('does not set the width of the element', () => { - instance._placeholderValue = 'This is a test'; - instance.element.value = 'Test'; - instance.setWidth(); - expect(calcWidthStub.callCount).to.equal(0); - }); - }); - }); - - describe('without a placeholder', () => { - it('sets the width of the element based on input value', () => { - instance.placeholder = null; - expect(instance.element.style.width).to.not.equal(inputWidth); - instance.setWidth(); - expect(calcWidthStub.callCount).to.equal(1); - expect(instance.element.style.width).to.equal(inputWidth); - }); + it('sets the width of the element based on input value and placeholder', () => { + instance.placeholder = 'This is a placeholder'; + instance.element.value = 'This is a value'; + expect(instance.element.style.width).to.not.equal('16ch'); + instance.setWidth(); + expect(instance.element.style.width).to.equal('16ch'); + expect(instance.element.style.minWidth).to.equal('22ch'); }); }); + */ describe('placeholder setter', () => { it('sets value of element to passed placeholder', () => { diff --git a/src/scripts/lib/utils.js b/src/scripts/lib/utils.js index f735ea1..cf3207b 100644 --- a/src/scripts/lib/utils.js +++ b/src/scripts/lib/utils.js @@ -113,54 +113,6 @@ export const strToEl = (() => { }; })(); -/** - * Determines the width of a passed input based on its value and passes - * it to the supplied callback function. - */ -export const calcWidthOfInput = (input, callback) => { - const value = input.value || input.placeholder; - let width = input.offsetWidth; - - if (value) { - const testEl = strToEl(`${sanitise(value)}`); - testEl.style.position = 'absolute'; - testEl.style.padding = '0'; - testEl.style.top = '-9999px'; - testEl.style.left = '-9999px'; - testEl.style.width = 'auto'; - testEl.style.whiteSpace = 'pre'; - - if (document.body.contains(input) && window.getComputedStyle) { - const inputStyle = window.getComputedStyle(input); - - if (inputStyle) { - testEl.style.fontSize = inputStyle.fontSize; - testEl.style.fontFamily = inputStyle.fontFamily; - testEl.style.fontWeight = inputStyle.fontWeight; - testEl.style.fontStyle = inputStyle.fontStyle; - testEl.style.letterSpacing = inputStyle.letterSpacing; - testEl.style.textTransform = inputStyle.textTransform; - testEl.style.paddingLeft = inputStyle.paddingLeft; - testEl.style.paddingRight = inputStyle.paddingRight; - } - } - - document.body.appendChild(testEl); - - requestAnimationFrame(() => { - if (value && testEl.offsetWidth !== input.offsetWidth) { - width = testEl.offsetWidth + 4; - } - - document.body.removeChild(testEl); - - callback.call(this, `${width}px`); - }); - } else { - callback.call(this, `${width}px`); - } -}; - export const sortByAlpha = (a, b) => { const labelA = `${a.label || a.value}`.toLowerCase(); const labelB = `${b.label || b.value}`.toLowerCase();