Skip to content

Commit fbef319

Browse files
committed
pdf-server: fix radio input → 'on'; use export value for consistency
pdf.js creates <input type=radio> without setting .value (pdf.mjs: 18138-18144), so target.value defaults to the HTML spec's 'on'. Our input listener read that → panel showed 'on' after clicking a radio, but baseline import correctly used the export value ('0') — so clicking then reverting showed two different strings for the same selection. Fix: store each radio widget's buttonValue during the annotation scan (we're already there for widget IDs), read it in the input listener via data-element-id. Now baseline, click, revert, and save all agree on the export value. (Form.pdf happens to use '0'/'1' as export values instead of 'Male'/'Female' — that's the form's design; the labels are just PDF text next to the widgets, not form data.)
1 parent f38eaad commit fbef319

1 file changed

Lines changed: 27 additions & 4 deletions

File tree

examples/pdf-server/src/mcp-app.ts

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ const redoStack: EditEntry[] = [];
119119

120120
// PDF.js form field name → annotation IDs mapping (for annotationStorage)
121121
const fieldNameToIds = new Map<string, string[]>();
122+
// Radio widget annotation ID → its export value (buttonValue). pdf.js
123+
// creates <input type=radio> without setting .value, so target.value
124+
// defaults to "on"; this map lets the input listener report the real value.
125+
const radioButtonValues = new Map<string, string>();
122126
// PDF.js form field name → page number mapping
123127
const fieldNameToPage = new Map<string, number>();
124128
// PDF.js form field name → human-readable label (from PDF TU / alternativeText)
@@ -3418,6 +3422,7 @@ async function buildFieldNameMap(
34183422
doc: pdfjsLib.PDFDocumentProxy,
34193423
): Promise<void> {
34203424
fieldNameToIds.clear();
3425+
radioButtonValues.clear();
34213426
fieldNameToPage.clear();
34223427
fieldNameToLabel.clear();
34233428
fieldNameToOrder.clear();
@@ -3457,6 +3462,14 @@ async function buildFieldNameMap(
34573462
ids.push(a.id);
34583463
fieldNameToIds.set(a.fieldName, ids);
34593464

3465+
// Radio buttons: pdf.js creates <input type=radio> WITHOUT setting
3466+
// .value, so reading target.value gives the HTML default "on".
3467+
// Remember each widget's export value so the input listener can
3468+
// report it instead.
3469+
if (a.radioButton && a.buttonValue != null) {
3470+
radioButtonValues.set(a.id, String(a.buttonValue));
3471+
}
3472+
34603473
if (!fieldNameToPage.has(a.fieldName)) {
34613474
fieldNameToPage.set(a.fieldName, pageNum);
34623475
}
@@ -4055,10 +4068,19 @@ formLayerEl.addEventListener("input", (e) => {
40554068
const target = e.target as HTMLInputElement | HTMLSelectElement;
40564069
const fieldName = target.name;
40574070
if (!fieldName) return;
4058-
const value =
4059-
target instanceof HTMLInputElement && target.type === "checkbox"
4060-
? target.checked
4061-
: target.value;
4071+
let value: string | boolean;
4072+
if (target instanceof HTMLInputElement && target.type === "checkbox") {
4073+
value = target.checked;
4074+
} else if (target instanceof HTMLInputElement && target.type === "radio") {
4075+
// pdf.js doesn't set .value on radio inputs → target.value defaults to
4076+
// "on". Use the widget's export value (buttonValue) so the panel and
4077+
// baseline agree on the same representation.
4078+
if (!target.checked) return; // unchecking siblings — ignore
4079+
const wid = target.getAttribute("data-element-id");
4080+
value = (wid && radioButtonValues.get(wid)) ?? target.value;
4081+
} else {
4082+
value = target.value;
4083+
}
40624084
formFieldValues.set(fieldName, value);
40634085
updateAnnotationsBadge();
40644086
renderAnnotationPanel();
@@ -4585,6 +4607,7 @@ async function reloadPdf(): Promise<void> {
45854607
currentMatchIndex = -1;
45864608
focusedFieldName = null;
45874609
fieldNameToIds.clear();
4610+
radioButtonValues.clear();
45884611
fieldNameToLabel.clear();
45894612
fieldNameToOrder.clear();
45904613
cachedFieldObjects = null;

0 commit comments

Comments
 (0)