Skip to content

Commit b267360

Browse files
committed
Use textareas, with a JS hack for height
1 parent e43023c commit b267360

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

src/pages/index.astro

+41-21
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,34 @@ const initialExample = examples.find(e => e.highlighted)?.title
1010

1111
<script>
1212
import {ppeg} from "ppegjs"
13+
const DESKTOP_SIZE = 768
1314

14-
const examplesSelect = document.querySelector<HTMLSelectElement>('#examples')
15-
if (!examplesSelect) throw new Error("No select element found")
16-
const grammar = document.querySelector<HTMLDivElement>('#grammar')
17-
if (!grammar) throw new Error("No grammar div found")
18-
const input = document.querySelector<HTMLDivElement>('#input')
19-
if (!input) throw new Error("No input div found")
20-
const output = document.querySelector<HTMLDivElement>('#output')
21-
if (!output) throw new Error("No output div found")
22-
const jsonCheckbox = document.querySelector<HTMLInputElement>('#json')
23-
if (!jsonCheckbox) throw new Error("No json checkbox found")
15+
const getElement = <T extends Element>(selector: string): T => {
16+
const element = document.querySelector<T>(selector);
17+
if (!element) throw new Error("No element found: " + selector);
18+
return element;
19+
}
20+
21+
const examplesSelect = getElement<HTMLSelectElement>('#examples')
22+
const grammar = getElement<HTMLTextAreaElement>('#grammar')
23+
const input = getElement<HTMLTextAreaElement>('#input')
24+
const output = getElement<HTMLTextAreaElement>('#output')
25+
const jsonCheckbox = getElement<HTMLInputElement>('#json')
2426

2527
const load = () => {
2628
const selected = examplesSelect.value
27-
const option = document.querySelector<HTMLOptionElement>(`#option-${selected}`)!
28-
grammar.innerText = option.dataset.grammar ?? "";
29-
input.innerText = option.dataset.input ?? "";
29+
const option = getElement<HTMLOptionElement>(`#option-${selected}`)
30+
grammar.value = option.dataset.grammar ?? "";
31+
input.value = option.dataset.input ?? "";
3032
run()
3133
}
3234

3335
const run = () => {
34-
const parser = ppeg.compile(grammar.innerText)
35-
const parse = parser.parse(input.innerText)
36+
const parser = ppeg.compile(grammar.value)
37+
const parse = parser.parse(input.value)
3638
const showJson = jsonCheckbox.checked
37-
if (parse.ok) output.textContent = parse.show_ptree(showJson);
38-
else output.textContent = parse.show_err();
39+
if (parse.ok) output.value = parse.show_ptree(showJson);
40+
else output.value = parse.show_err();
3941
}
4042

4143
const debounce = function (fn: Function, delay: number = 300) {
@@ -51,7 +53,25 @@ const initialExample = examples.find(e => e.highlighted)?.title
5153

5254
const autoparse = debounce(run)
5355

54-
examplesSelect.addEventListener('change', load)
56+
examplesSelect.addEventListener('change', load);
57+
// A little hack to ensure the textarea heights grow with content
58+
[grammar, input, output].forEach(el => el.addEventListener('input', (e) => {
59+
if (document.body.clientWidth <= DESKTOP_SIZE) {
60+
el.style.height = "0"
61+
el.style.height = el.scrollHeight + "px"
62+
}
63+
}))
64+
// The same code needs to run in case we resize from big to small
65+
window.addEventListener("resize", () => {
66+
[grammar, input, output].forEach(el => {
67+
if (document.body.clientWidth <= DESKTOP_SIZE) {
68+
el.style.height = "0"
69+
el.style.height = el.scrollHeight + "px"
70+
} else {
71+
el.style.height = "auto"
72+
}
73+
})
74+
})
5575
grammar.addEventListener('input', autoparse)
5676
input.addEventListener('input', autoparse)
5777
jsonCheckbox.addEventListener('change', run)
@@ -162,13 +182,13 @@ const initialExample = examples.find(e => e.highlighted)?.title
162182
</select>
163183
</span>
164184
</div>
165-
<div contenteditable="true" role="textbox" id='grammar'></div>
185+
<textarea id='grammar'></textarea>
166186
</div>
167187
<div class='input'>
168188
<div class='header'>
169189
<label for="input">Input</label>
170190
</div>
171-
<div contenteditable="true" role="textbox" id='input'"></div>
191+
<textarea id='input'"></textarea>
172192
</div>
173193
<div class='output'>
174194
<div class='header'>Parse Tree
@@ -177,7 +197,7 @@ const initialExample = examples.find(e => e.highlighted)?.title
177197
<input type="checkbox" id="json" name="json">
178198
</label>
179199
</div>
180-
<div id='output'></div>
200+
<textarea id='output' disabled></textarea>
181201
</div>
182202
<div class="footer">Copyright 2024</div>
183203
</Layout>

0 commit comments

Comments
 (0)