Skip to content

Commit

Permalink
[JS] Use beforeinput event to trigger a keystroke event in the sandbox
Browse files Browse the repository at this point in the history
 - it aims to fix issue mozilla#14307;
 - this event has been added recently in Firefox and we can now use it;
 - fix few bugs in aform.js or in annotation_layer.js;
 - add some integration tests to test keystroke events (see `AFSpecial_Keystroke`);
 - make dispatchEvent in the quickjs sandbox async.
  • Loading branch information
calixteman authored and bh213 committed Jun 3, 2022
1 parent b91640e commit 0c125da
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 45 deletions.
Binary file added out.pdf
Binary file not shown.
44 changes: 10 additions & 34 deletions src/display/annotation_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -780,7 +780,7 @@ class WidgetAnnotationElement extends AnnotationElement {
detail: {
id: this.data.id,
name: eventName,
value: event.target.checked,
value: valueGetter(event),
},
});
});
Expand Down Expand Up @@ -923,8 +923,6 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const elementData = {
userValue: null,
formattedValue: null,
beforeInputSelectionRange: null,
beforeInputValue: null,
};

if (this.data.multiLine) {
Expand Down Expand Up @@ -965,7 +963,6 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
}
// Reset the cursor position to the start of the field (issue 12359).
event.target.scrollLeft = 0;
elementData.beforeInputSelectionRange = null;
};

if (this.enableScripting && this.hasJSActions) {
Expand Down Expand Up @@ -1007,7 +1004,6 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
// Even if the field hasn't any actions
// leaving it can still trigger some actions with Calculate
element.addEventListener("keydown", event => {
elementData.beforeInputValue = event.target.value;
// if the key is one of Escape, Enter or Tab
// then the data are committed
let commitKey = -1;
Expand Down Expand Up @@ -1039,9 +1035,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const _blurListener = blurListener;
blurListener = null;
element.addEventListener("blur", event => {
elementData.userValue = event.target.value;
if (this._mouseState.isDown) {
// Focus out using the mouse: data are committed
elementData.userValue = event.target.value;
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
source: this,
detail: {
Expand All @@ -1057,42 +1053,22 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
}
_blurListener(event);
});
element.addEventListener("mousedown", event => {
elementData.beforeInputValue = event.target.value;
elementData.beforeInputSelectionRange = null;
});
element.addEventListener("keyup", event => {
// keyup is triggered after input
if (event.target.selectionStart === event.target.selectionEnd) {
elementData.beforeInputSelectionRange = null;
}
});
element.addEventListener("select", event => {
elementData.beforeInputSelectionRange = [
event.target.selectionStart,
event.target.selectionEnd,
];
});

if (this.data.actions?.Keystroke) {
// We should use beforeinput but this
// event isn't available in Firefox
element.addEventListener("input", event => {
let selStart = -1;
let selEnd = -1;
if (elementData.beforeInputSelectionRange) {
[selStart, selEnd] = elementData.beforeInputSelectionRange;
}
element.addEventListener("beforeinput", event => {
elementData.formattedValue = "";
const { data, target } = event;
const { value, selectionStart, selectionEnd } = target;
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
source: this,
detail: {
id,
name: "Keystroke",
value: elementData.beforeInputValue,
change: event.data,
value,
change: data,
willCommit: false,
selStart,
selEnd,
selStart: selectionStart,
selEnd: selectionEnd,
},
});
});
Expand Down
2 changes: 1 addition & 1 deletion src/pdf.sandbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class Sandbox {
}

dispatchEvent(event) {
this.support.callSandboxFunction("dispatchEvent", event);
this.support?.callSandboxFunction("dispatchEvent", event);
}

dumpMemoryUse() {
Expand Down
12 changes: 4 additions & 8 deletions src/scripting_api/aform.js
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ class AForm {

const event = globalThis.event;
const value = this.AFMergeChange(event);
if (!value) {
return;
}

const checkers = new Map([
["9", char => char >= "0" && char <= "9"],
[
Expand Down Expand Up @@ -498,10 +502,6 @@ class AForm {
return true;
}

if (!value) {
return;
}

const err = `${GlobalConstants.IDS_INVALID_VALUE} = "${cMask}"`;

if (value.length > cMask.length) {
Expand Down Expand Up @@ -538,10 +538,6 @@ class AForm {

AFSpecial_Keystroke(psf) {
const event = globalThis.event;
if (!event.value) {
return;
}

psf = this.AFMakeNumber(psf);

let formatStr;
Expand Down
8 changes: 8 additions & 0 deletions src/scripting_api/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ class EventDispatcher {
value: savedChange.value,
selRange: [savedChange.selStart, savedChange.selEnd],
});
} else {
// Entry is not valid (rc == false) and it's a commit
// so just clear the field.
source.obj._send({
id: source.obj._id,
value: "",
selRange: [0, 0],
});
}
}
}
Expand Down
Loading

0 comments on commit 0c125da

Please sign in to comment.