Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS -- Add support for buttons #12637

Merged
merged 1 commit into from
Dec 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1944,18 +1944,19 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {

getFieldObject() {
let type = "button";
let value = null;
let exportValues;
if (this.data.checkBox) {
type = "checkbox";
value = this.data.fieldValue && this.data.fieldValue !== "Off";
exportValues = this.data.exportValue;
} else if (this.data.radioButton) {
type = "radiobutton";
value = this.data.fieldValue === this.data.buttonValue;
exportValues = this.data.buttonValue;
}
return {
id: this.data.id,
value,
value: this.data.fieldValue || null,
defaultValue: this.data.defaultFieldValue,
exportValues,
editable: !this.data.readOnly,
name: this.data.fieldName,
rect: this.data.rect,
Expand Down Expand Up @@ -2036,6 +2037,7 @@ class ChoiceWidgetAnnotation extends WidgetAnnotation {
editable: !this.data.readOnly,
name: this.data.fieldName,
rect: this.data.rect,
numItems: this.data.fieldValue.length,
multipleSelection: this.data.multiSelect,
hidden: this.data.hidden,
actions: this.data.actions,
Expand Down
3 changes: 3 additions & 0 deletions src/display/annotation_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
value() {
elementData.userValue = detail.value || "";
storage.setValue(id, { value: elementData.userValue.toString() });
if (!elementData.formattedValue) {
event.target.value = elementData.userValue;
}
},
valueAsString() {
elementData.formattedValue = detail.valueAsString || "";
Expand Down
3 changes: 3 additions & 0 deletions src/scripting_api/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ class EventDispatcher {
if (source.obj._isButton()) {
source.obj._id = id;
event.value = source.obj._getExportValue(event.value);
if (name === "Action") {
source.obj._value = event.value;
}
}

if (name === "Keystroke") {
Expand Down
148 changes: 141 additions & 7 deletions src/scripting_api/field.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Field extends PDFObject {
this.highlight = data.highlight;
this.lineWidth = data.lineWidth;
this.multiline = data.multiline;
this.multipleSelection = data.multipleSelection;
this.multipleSelection = !!data.multipleSelection;
this.name = data.name;
this.numItems = data.numItems;
this.page = data.page;
Expand All @@ -66,15 +66,12 @@ class Field extends PDFObject {
this.textSize = data.textSize;
this.type = data.type;
this.userName = data.userName;
this.value = data.value || "";

// Need getter/setter
this._valueAsString = data.valueAsString;

// Private
this._document = data.doc;
this._value = data.value || "";
this._valueAsString = data.valueAsString;
this._actions = createActionsMap(data.actions);

this._fillColor = data.fillColor || ["T"];
this._strokeColor = data.strokeColor || ["G", 0];
this._textColor = data.textColor || ["G", 0];
Expand Down Expand Up @@ -112,6 +109,16 @@ class Field extends PDFObject {
}
}

get value() {
return this._value;
}

set value(value) {
if (!this.multipleSelection) {
this._value = value;
}
}

get valueAsString() {
return this._valueAsString;
}
Expand All @@ -120,6 +127,16 @@ class Field extends PDFObject {
this._valueAsString = val ? val.toString() : "";
}

checkThisBox(nWidget, bCheckIt = true) {}

isBoxChecked(nWidget) {
return false;
}

isDefaultChecked(nWidget) {
return false;
}

setAction(cTrigger, cScript) {
if (typeof cTrigger !== "string" || typeof cScript !== "string") {
return;
Expand Down Expand Up @@ -159,4 +176,121 @@ class Field extends PDFObject {
}
}

export { Field };
class RadioButtonField extends Field {
constructor(otherButtons, data) {
super(data);

this.exportValues = [this.exportValues];
this._radioIds = [this._id];
this._radioActions = [this._actions];

for (const radioData of otherButtons) {
this.exportValues.push(radioData.exportValues);
this._radioIds.push(radioData.id);
this._radioActions.push(createActionsMap(radioData.actions));
if (this._value === radioData.exportValues) {
this._id = radioData.id;
}
}
}

get value() {
return this._value;
}

set value(value) {
const i = this.exportValues.indexOf(value);
if (0 <= i && i < this._radioIds.length) {
this._id = this._radioIds[i];
this._value = value;
} else if (value === "Off" && this._radioIds.length === 2) {
const nextI = (1 + this._radioIds.indexOf(this._id)) % 2;
this._id = this._radioIds[nextI];
this._value = this.exportValues[nextI];
}
}

checkThisBox(nWidget, bCheckIt = true) {
if (nWidget < 0 || nWidget >= this._radioIds.length || !bCheckIt) {
return;
}

this._id = this._radioIds[nWidget];
this._value = this.exportValues[nWidget];
this._send({ id: this._id, value: this._value });
}

isBoxChecked(nWidget) {
return (
nWidget >= 0 &&
nWidget < this._radioIds.length &&
this._id === this._radioIds[nWidget]
);
}

isDefaultChecked(nWidget) {
return (
nWidget >= 0 &&
nWidget < this.exportValues.length &&
this.defaultValue === this.exportValues[nWidget]
);
}

_getExportValue(state) {
const i = this._radioIds.indexOf(this._id);
return this.exportValues[i];
}

_runActions(event) {
const i = this._radioIds.indexOf(this._id);
this._actions = this._radioActions[i];
return super._runActions(event);
}

_isButton() {
return true;
}
}

class CheckboxField extends RadioButtonField {
get value() {
return this._value;
}

set value(value) {
if (value === "Off") {
this._value = "Off";
} else {
super.value = value;
}
}

_getExportValue(state) {
return state ? super._getExportValue(state) : "Off";
}

isBoxChecked(nWidget) {
if (this._value === "Off") {
return false;
}
return super.isBoxChecked(nWidget);
}

isDefaultChecked(nWidget) {
if (this.defaultValue === "Off") {
return this._value === "Off";
}
return super.isDefaultChecked(nWidget);
}

checkThisBox(nWidget, bCheckIt = true) {
if (nWidget < 0 || nWidget >= this._radioIds.length) {
return;
}
this._id = this._radioIds[nWidget];
this._value = bCheckIt ? this.exportValues[nWidget] : "Off";
this._send({ id: this._id, value: this._value });
}
}

export { CheckboxField, Field, RadioButtonField };
19 changes: 16 additions & 3 deletions src/scripting_api/initialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ import {
Trans,
ZoomType,
} from "./constants.js";
import { CheckboxField, Field, RadioButtonField } from "./field.js";
import { AForm } from "./aform.js";
import { App } from "./app.js";
import { Color } from "./color.js";
import { Console } from "./console.js";
import { Doc } from "./doc.js";
import { Field } from "./field.js";
import { ProxyHandler } from "./proxy.js";
import { Util } from "./util.js";

Expand Down Expand Up @@ -74,10 +74,23 @@ function initSandbox(params) {
obj.send = send;
obj.globalEval = globalEval;
obj.doc = _document.wrapped;
const field = new Field(obj);
let field;
if (obj.type === "radiobutton") {
const otherButtons = objs.slice(1);
field = new RadioButtonField(otherButtons, obj);
} else if (obj.type === "checkbox") {
const otherButtons = objs.slice(1);
field = new CheckboxField(otherButtons, obj);
} else {
field = new Field(obj);
}

const wrapped = new Proxy(field, proxyHandler);
doc._addField(name, wrapped);
app._objects[obj.id] = { obj: field, wrapped };
const _object = { obj: field, wrapped };
for (const object of objs) {
app._objects[object.id] = _object;
}
}
}

Expand Down
Loading