Skip to content

Commit ce86dc2

Browse files
authored
Merge pull request #3090 from codefori/fixEnterForms
Fix Enter key handling in Custom UI and Editors forms
2 parents fa169c7 + 17ed6df commit ce86dc2

File tree

2 files changed

+47
-70
lines changed

2 files changed

+47
-70
lines changed

src/editors/customEditorProvider.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,25 @@ export class CustomEditor<T> extends CustomHTML implements vscode.CustomDocument
1515

1616
protected getSpecificScript() {
1717
return /* javascript */ `
18+
const theForm = document.querySelector('#laforma');
1819
for (const field of submitfields) {
1920
const fieldElement = document.getElementById(field);
2021
fieldElement.addEventListener(inputFields.some(f => f.id === field) ? 'input' : 'change', function(event) {
2122
event?.preventDefault();
2223
const data = {};
23-
new FormData(document.querySelector('#laforma')).entries().forEach(([key, value]) => data[key] = value);
24+
new FormData(theForm).entries().forEach(([key, value]) => data[key] = value);
2425
2526
// Convert checkboxes value to actual boolean
2627
checkboxes.forEach(checkbox => data[checkbox] = (data[checkbox] === 'on'));
2728
2829
data.valid = validateInputs();
2930
3031
vscode.postMessage({ type: 'dataChange', data });
31-
});
32+
});
3233
}
34+
35+
//Prevent form from being submitted
36+
theForm.addEventListener("submit", (event) => event?.preventDefault());
3337
`;
3438
}
3539

src/webviews/CustomUI.ts

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export class CustomHTML extends Section {
166166
}
167167

168168
protected getHTML(panel: vscode.WebviewPanel, title: string) {
169-
const notInputFields = [`submit`, `buttons`, `tree`, `hr`, `paragraph`, `tabs`, `complexTabs`, 'browser'] as FieldType[];
169+
const notInputFields = [`submit`, `buttons`, `tree`, `hr`, `paragraph`, `tabs`, `complexTabs`, 'browser', 'heading'] as FieldType[];
170170
const trees = this.fields.filter(field => [`tree`, 'browser'].includes(field.type));
171171

172172
const complexTabFields = this.fields.filter(field => field.type === `complexTabs`).map(tabs => tabs.complexTabItems?.map(tab => tab.fields));
@@ -175,12 +175,12 @@ export class CustomHTML extends Section {
175175
return /*html*/`
176176
<!DOCTYPE html>
177177
<html lang="en">
178-
178+
179179
<head>
180180
<meta charset="UTF-8">
181181
<meta name="viewport" content="width=device-width, initial-scale=1.0">
182182
<title>${title}</title>
183-
183+
184184
<script type="module">${vscodeweb}</script>
185185
<style>
186186
@media only screen and (min-width: 750px) {
@@ -216,13 +216,13 @@ export class CustomHTML extends Section {
216216
overflow: auto;
217217
}
218218
219-
pre{
219+
pre{
220220
background-color: var(--vscode-textPreformat-background);
221221
}
222222
${this.options?.css || ""}
223223
</style>
224224
</head>
225-
225+
226226
<body>
227227
${this.options?.fullPage ?
228228
this.fields.map(field => field.getHTML()).join(``) :
@@ -231,9 +231,9 @@ export class CustomHTML extends Section {
231231
${this.fields.map(field => field.getHTML()).join(``)}
232232
</form>
233233
`
234-
}
234+
}
235235
</body>
236-
236+
237237
<script>
238238
(function () {
239239
const vscode = acquireVsCodeApi();
@@ -272,7 +272,7 @@ export class CustomHTML extends Section {
272272
}
273273
}
274274
validateInputs(response.field);
275-
}
275+
}
276276
}
277277
});
278278
@@ -310,13 +310,13 @@ export class CustomHTML extends Section {
310310
}
311311
}
312312
313-
// If not validating a specific field,
313+
// If not validating a specific field,
314314
// then we can enable/disable certain buttons
315315
if (!optionalId) {
316316
for (const fieldData of groupButtons) {
317317
if (fieldData.requiresValidation) {
318318
const field = fieldData.id;
319-
319+
320320
let button = document.getElementById(field);
321321
if (isValid) {
322322
button.removeAttribute("disabled");
@@ -328,7 +328,7 @@ export class CustomHTML extends Section {
328328
}
329329
330330
return isValid;
331-
}
331+
}
332332
333333
const treeItemClick = (treeId, type, value) => {
334334
if(type === "browse"){
@@ -337,7 +337,7 @@ export class CustomHTML extends Section {
337337
}
338338
else{
339339
vscode.postMessage({ type, data: {treeId, value} });
340-
}
340+
}
341341
}
342342
343343
const doFileRequest = (event, fieldId) => {
@@ -351,7 +351,7 @@ export class CustomHTML extends Section {
351351
for (const field of inputFields) {
352352
const fieldElement = document.getElementById(field.id);
353353
fieldElement.addEventListener("change", (e) => validateInputs());
354-
}
354+
}
355355
356356
// This is used to read the file in order to get the real path.
357357
for (const field of filefields) {
@@ -362,23 +362,23 @@ export class CustomHTML extends Section {
362362
}
363363
364364
document.addEventListener('DOMContentLoaded', () => {
365-
validateInputs();
365+
validateInputs();
366366
var currentTree;
367367
${trees.map(tree => /* javascript */`
368368
currentTree = document.getElementById('${tree.id}');
369369
currentTree.data = ${JSON.stringify(tree.treeList)};
370370
currentTree.addEventListener('vsc-tree-select', (event) => {
371371
console.log(JSON.stringify(event.detail));
372372
if (event.detail.itemType === 'leaf') {
373-
treeItemClick('${tree.id}', '${tree.treeLeafAction}', event.detail.value);
373+
treeItemClick('${tree.id}', '${tree.treeLeafAction}', event.detail.value);
374374
}
375375
});`
376376
)}
377377
});
378378
${this.getSpecificScript()}
379379
}())
380380
</script>
381-
381+
382382
</html>`;
383383
}
384384
}
@@ -387,7 +387,7 @@ export class CustomUI extends CustomHTML {
387387
/**
388388
* If no callback is provided, a Promise will be returned.
389389
* If the page is already opened, it grabs the focus and return no Promise (as it's alreay handled by the first call).
390-
*
390+
*
391391
* @param title the title displayed in the webview tab
392392
* @param checkData an optional function that can check and updates the data before they are returned. If it returns `false`, the view will stay open.
393393
* @returns a Promise<Page<T>> if no callback is provided
@@ -464,59 +464,32 @@ export class CustomUI extends CustomHTML {
464464

465465
protected getSpecificScript() {
466466
return /* javascript */ `
467-
const doDone = (event, buttonId) => {
468-
console.log('submit now!!', buttonId)
467+
const theForm = document.querySelector('#laforma');
468+
469+
const doDone = (event, button) => {
470+
console.log('submit now!!', button || 'enter pressed')
469471
event?.preventDefault();
470-
471-
const data = { buttons: buttonId };
472-
new FormData(document.querySelector('#laforma')).entries().forEach(([key, value]) => data[key] = value);
472+
const isValid = (!button || button.requiresValidation) ? validateInputs() : true;
473+
if (isValid) {
474+
const data = { buttons: button?.id };
475+
new FormData(theForm).entries().forEach(([key, value]) => data[key] = value);
473476
474-
// Convert checkboxes value to actual boolean
475-
checkboxes.forEach(checkbox => data[checkbox] = (data[checkbox] === 'on'));
477+
// Convert checkboxes value to actual boolean
478+
checkboxes.forEach(checkbox => data[checkbox] = (data[checkbox] === 'on'));
476479
477-
vscode.postMessage({ type: 'submit', data });
480+
vscode.postMessage({ type: 'submit', data });
481+
}
478482
};
479483
484+
//Pressing enter will submit the form
485+
theForm.addEventListener("submit", doDone);
486+
480487
// Now many buttons can be pressed to submit
481488
for (const fieldData of groupButtons) {
482-
const field = fieldData.id;
483-
484-
console.log('group button', fieldData, document.getElementById(field));
485-
var button = document.getElementById(field);
486-
487-
const submitButtonAction = (event) => {
488-
const isValid = fieldData.requiresValidation ? validateInputs() : true;
489-
console.log({requiresValidation: fieldData.requiresValidation, isValid});
490-
if (isValid) doDone(event, field);
491-
}
489+
const button = document.getElementById(fieldData.id);
492490
493-
button.onclick = submitButtonAction;
494-
button.onKeyDown = submitButtonAction;
495-
}
496-
497-
for (const field of submitfields) {
498-
const currentElement = document.getElementById(field);
499-
if (currentElement.hasAttribute('rows')) {
500-
currentElement
501-
.addEventListener('keyup', function(event) {
502-
event.preventDefault();
503-
if (event.keyCode === 13 && event.altKey) {
504-
if (validateInputs()) {
505-
doDone();
506-
}
507-
}
508-
});
509-
} else {
510-
currentElement
511-
.addEventListener('keyup', function(event) {
512-
event.preventDefault();
513-
if (event.keyCode === 13) {
514-
if (validateInputs()) {
515-
doDone();
516-
}
517-
}
518-
});
519-
}
491+
button.onclick = () => doDone(event, fieldData);
492+
button.onKeyDown = () => doDone(event, fieldData);
520493
}
521494
`;
522495
}
@@ -623,13 +596,13 @@ export class Field {
623596
return /* html */`
624597
<vscode-form-group variant="settings-group">
625598
${this.renderLabel()}
626-
${this.renderDescription()}
627-
<${tag} class="long-input" id="${this.id}" name="${this.id}"
628-
${this.inputType ? `type="${this.inputType}"` : ``}
629-
${this.default ? `value="${this.default}"` : ``}
630-
${this.readonly ? `readonly` : ``}
599+
${this.renderDescription()}
600+
<${tag} class="long-input" id="${this.id}" name="${this.id}"
601+
${this.inputType ? `type="${this.inputType}"` : ``}
602+
${this.default ? `value="${this.default}"` : ``}
603+
${this.readonly ? `readonly` : ``}
631604
${multiline ? `rows="${this.rows}" resize="vertical"` : ''}
632-
${this.minlength ? `minlength="${this.minlength}"` : ``}
605+
${this.minlength ? `minlength="${this.minlength}"` : ``}
633606
${this.maxlength ? `maxlength="${this.maxlength}"` : ``}
634607
${this.min ? `min="${this.min}"` : ``}
635608
${this.max ? `max="${this.max}"` : ``}

0 commit comments

Comments
 (0)