Skip to content

Commit e80ba70

Browse files
Auto-fit input and output boxes to contents
1 parent 331fed9 commit e80ba70

File tree

5 files changed

+61
-11
lines changed

5 files changed

+61
-11
lines changed

demo/index.html

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,7 @@
8383
<label for="words">
8484
Words or phrases the Regular Expression should match:
8585
</label>
86-
<textarea
87-
required
88-
id="words"
89-
class="form-control js-words"
90-
></textarea>
86+
<textarea class="form-control js-words" required rows="1"></textarea>
9187
</div>
9288

9389
<div class="form-inline">
@@ -151,6 +147,7 @@
151147
readonly="readonly"
152148
id="output"
153149
class="form-control js-output"
150+
rows="1"
154151
></textarea>
155152
</div>
156153
</section>

demo/src/demo.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { condense, condenseIgnoreCase } from '../../src/index';
2+
import { autoExpandTextarea } from './utils/auto-expand-field';
23
import { parseString, WhitespaceHandling } from './utils/wordList';
34

45
const { Preserve, TrimLeadingAndTrailing } = WhitespaceHandling;
@@ -29,6 +30,7 @@ function generatePattern(words: string): RegExp {
2930
let clearSuccessIndicatorHandle: number;
3031
function displayPattern(pattern: RegExp): void {
3132
$output.value = pattern.toString();
33+
$output.dispatchEvent(new Event('input'));
3234

3335
// Temporarily style the output box as valid
3436
$output.classList.add('is-valid');
@@ -55,12 +57,16 @@ function onClickGenerate(): void {
5557
}
5658
$submit.addEventListener('click', onClickGenerate);
5759

60+
autoExpandTextarea($input);
61+
autoExpandTextarea($output);
62+
5863
((): void => {
5964
const exampleInput =
6065
'Alabama, Alaska, Arizona, Arkansas, California, ' +
6166
'Colorado, Connecticut, Delaware, Florida, Georgia';
6267

6368
$input.value = exampleInput;
69+
$input.dispatchEvent(new Event('input'));
6470
const pattern = generatePattern(exampleInput);
6571
displayPattern(pattern);
6672
})();
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/* eslint no-param-reassign: ["error", { "props": true, "ignorePropertyModificationsFor": ["field"] }] */
2+
3+
/* eslint-disable @typescript-eslint/no-explicit-any */
4+
/**
5+
* @see https://gist.github.com/fr-ser/ded7690b245223094cd876069456ed6c
6+
*/
7+
function debounce<F extends Function>(func: F, wait: number): F {
8+
let timeoutID: number;
9+
10+
return (function debounced(this: any, ...args: any[]) {
11+
clearTimeout(timeoutID);
12+
13+
timeoutID = window.setTimeout(() => func.apply(this, args), wait);
14+
} as any) as F;
15+
}
16+
/* eslint-enable @typescript-eslint/no-explicit-any */
17+
18+
/**
19+
* Grow or shrink a <textarea> field's height to fit its contents.
20+
* From https://codepen.io/vsync/pen/frudD.
21+
* @param field The <textarea> field to resize
22+
*/
23+
export function autoExpandTextarea(field: HTMLTextAreaElement): void {
24+
field.classList.add('automaticHeight');
25+
26+
const fieldStyles = window.getComputedStyle(field);
27+
const lineHeightStyle = fieldStyles.getPropertyValue('line-height');
28+
const pixelsPerRow = parseInt(lineHeightStyle, 10);
29+
30+
const minVisibleRows = field.rows;
31+
32+
const savedValue = field.value;
33+
field.value = '';
34+
const baseScrollHeight = field.scrollHeight;
35+
field.value = savedValue;
36+
37+
function recalculateHeight(): void {
38+
field.rows = minVisibleRows;
39+
const currentHeightPixels = field.scrollHeight - baseScrollHeight;
40+
const rows = Math.ceil(currentHeightPixels / pixelsPerRow);
41+
field.rows = minVisibleRows + rows;
42+
}
43+
44+
field.addEventListener('input', recalculateHeight, false);
45+
window.addEventListener('resize', debounce(recalculateHeight, 100), false);
46+
}

demo/styles.css

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,18 @@
1313
padding-top: 1em;
1414
}
1515

16+
.automaticHeight {
17+
box-sizing: padding-box;
18+
overflow: hidden;
19+
resize: none;
20+
}
21+
1622
input:invalid,
1723
textarea:invalid,
1824
select:invalid {
1925
border: 2px solid red;
2026
}
2127

22-
#words {
23-
height: 15em;
24-
}
25-
2628
.form-inline {
2729
flex-direction: column;
2830
}
@@ -37,8 +39,6 @@ select:invalid {
3739
}
3840

3941
#output {
40-
height: 5em;
41-
4242
border-width: 4px;
4343
transition: border-color 0.6s ease-out;
4444
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"jest": {
3030
"collectCoverageFrom": [
3131
"**/src/**/?*.(js|ts)",
32+
"!demo/src/utils/auto-expand-field.ts",
3233
"!demo/src/demo.ts"
3334
],
3435
"preset": "ts-jest",

0 commit comments

Comments
 (0)