diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js index af1d98343..1e0eb863a 100644 --- a/src/display/annotation_layer.js +++ b/src/display/annotation_layer.js @@ -582,6 +582,39 @@ class WidgetAnnotationElement extends AnnotationElement { } } } + + _setColor(event) { + const { detail, target } = event; + const { style } = target; + for (const name of [ + "bgColor", + "fillColor", + "fgColor", + "textColor", + "borderColor", + "strokeColor", + ]) { + let color = detail[name]; + if (!color) { + continue; + } + color = ColorConverters[`${color[0]}_HTML`](color.slice(1)); + switch (name) { + case "bgColor": + case "fillColor": + style.backgroundColor = color; + break; + case "fgColor": + case "textColor": + style.color = color; + break; + case "borderColor": + case "strokeColor": + style.borderColor = color; + break; + } + } + } } class TextWidgetAnnotationElement extends WidgetAnnotationElement { @@ -644,7 +677,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { } }); - element.addEventListener("updatefromsandbox", function (event) { + element.addEventListener("updatefromsandbox", event => { const { detail } = event; const actions = { value() { @@ -686,16 +719,11 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement { event.target.setSelectionRange(selStart, selEnd); } }, - strokeColor() { - const color = detail.strokeColor; - event.target.style.color = ColorConverters[`${color[0]}_HTML`]( - color.slice(1) - ); - }, }; Object.keys(detail) .filter(name => name in actions) .forEach(name => actions[name]()); + this._setColor(event); }); // Even if the field hasn't any actions @@ -929,6 +957,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { Object.keys(detail) .filter(name => name in actions) .forEach(name => actions[name]()); + this._setColor(event); }); this._setEventListeners( @@ -1018,6 +1047,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { Object.keys(detail) .filter(name => name in actions) .forEach(name => actions[name]()); + this._setColor(event); }); this._setEventListeners( @@ -1226,6 +1256,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { Object.keys(detail) .filter(name => name in actions) .forEach(name => actions[name]()); + this._setColor(event); }); selectElement.addEventListener("input", event => { diff --git a/src/scripting_api/aform.js b/src/scripting_api/aform.js index ee61a4f80..f5de721cf 100644 --- a/src/scripting_api/aform.js +++ b/src/scripting_api/aform.js @@ -529,7 +529,7 @@ class AForm { event.rc = false; return; } - event.value += cMask.subString(value.length); + event.value += cMask.substring(value.length); return; } diff --git a/src/scripting_api/field.js b/src/scripting_api/field.js index 6fa16adad..3435957a8 100644 --- a/src/scripting_api/field.js +++ b/src/scripting_api/field.js @@ -140,6 +140,14 @@ class Field extends PDFObject { } } + get bgColor() { + return this.fillColor; + } + + set bgColor(color) { + this.fillColor = color; + } + get numItems() { if (!this._isChoice) { throw new Error("Not a choice widget"); @@ -161,6 +169,14 @@ class Field extends PDFObject { } } + get borderColor() { + return this.strokeColor; + } + + set borderColor(color) { + this.strokeColor = color; + } + get textColor() { return this._textColor; } @@ -171,6 +187,14 @@ class Field extends PDFObject { } } + get fgColor() { + return this.textColor; + } + + set fgColor(color) { + this.textColor = color; + } + get value() { return this._value; } diff --git a/test/integration/scripting_spec.js b/test/integration/scripting_spec.js index 2fedfc7a3..ecae8f4df 100644 --- a/test/integration/scripting_spec.js +++ b/test/integration/scripting_spec.js @@ -630,4 +630,53 @@ describe("Interaction", () => { ); }); }); + + describe("in js-colors.pdf", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("js-colors.pdf", "#\\33 4R"); + }); + + it("must changes colors", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + for (const [name, ref] of [ + ["Text1", "#\\33 4R"], + ["Check1", "#\\33 5R"], + ["Radio1", "#\\33 7R"], + ["Choice1", "#\\33 8R"], + ]) { + await clearInput(page, "#\\33 4R"); + await page.type("#\\33 4R", `${name}`, { + delay: 10, + }); + await page.click("[data-annotation-id='41R']"); + let color = await page.$eval( + ref, + el => getComputedStyle(el).backgroundColor + ); + expect(color) + .withContext(`In ${browserName}`) + .toEqual("rgb(255, 0, 0)"); + + await page.click("[data-annotation-id='43R']"); + color = await page.$eval(ref, el => getComputedStyle(el).color); + expect(color) + .withContext(`In ${browserName}`) + .toEqual("rgb(0, 255, 0)"); + + await page.click("[data-annotation-id='44R']"); + color = await page.$eval( + ref, + el => getComputedStyle(el)["border-top-color"] + ); + expect(color) + .withContext(`In ${browserName}`) + .toEqual("rgb(0, 0, 255)"); + } + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index ddb5fcee3..f5e03e23c 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -245,6 +245,7 @@ !personwithdog.pdf !helloworld-bad.pdf !zerowidthline.pdf +!js-colors.pdf !issue12841_reduced.pdf !bug868745.pdf !mmtype1.pdf diff --git a/test/pdfs/js-colors.pdf b/test/pdfs/js-colors.pdf new file mode 100644 index 000000000..5bf827353 Binary files /dev/null and b/test/pdfs/js-colors.pdf differ diff --git a/test/unit/scripting_spec.js b/test/unit/scripting_spec.js index 9c5ca4460..9841f895e 100644 --- a/test/unit/scripting_spec.js +++ b/test/unit/scripting_spec.js @@ -1166,6 +1166,18 @@ describe("Scripting", function () { value: "3F?", selRange: [3, 3], }); + + send_queue.delete(refId); + await sandbox.dispatchEventInSandbox({ + id: refId, + value: "3F?", + change: "0", + name: "Keystroke", + willCommit: true, + selStart: 3, + selEnd: 3, + }); + expect(send_queue.has(refId)).toEqual(false); }); });