Merge pull request #14869 from calixteman/14862
[JS] Fix few bugs present in the pdf for issue #14862
This commit is contained in:
commit
8135d7ccf6
@ -1518,7 +1518,8 @@ class WidgetAnnotation extends Annotation {
|
||||
const storageEntry = annotationStorage
|
||||
? annotationStorage.get(this.data.id)
|
||||
: undefined;
|
||||
let value = storageEntry && storageEntry.value;
|
||||
let value =
|
||||
storageEntry && (storageEntry.formattedValue || storageEntry.value);
|
||||
if (value === undefined) {
|
||||
if (!this._hasValueFromXFA || this.appearance) {
|
||||
// The annotation hasn't been rendered so use the appearance.
|
||||
@ -1981,7 +1982,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
||||
return {
|
||||
id: this.data.id,
|
||||
value: this.data.fieldValue,
|
||||
defaultValue: this.data.defaultFieldValue,
|
||||
defaultValue: this.data.defaultFieldValue || "",
|
||||
multiline: this.data.multiLine,
|
||||
password: this.hasFieldFlag(AnnotationFieldFlag.PASSWORD),
|
||||
charLimit: this.data.maxLen,
|
||||
|
@ -297,6 +297,110 @@ class AnnotationElement {
|
||||
return container;
|
||||
}
|
||||
|
||||
get _commonActions() {
|
||||
const setColor = (jsName, styleName, event) => {
|
||||
const color = event.detail[jsName];
|
||||
event.target.style[styleName] = ColorConverters[`${color[0]}_HTML`](
|
||||
color.slice(1)
|
||||
);
|
||||
};
|
||||
|
||||
return shadow(this, "_commonActions", {
|
||||
display: event => {
|
||||
const hidden = event.detail.display % 2 === 1;
|
||||
event.target.style.visibility = hidden ? "hidden" : "visible";
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
hidden,
|
||||
print: event.detail.display === 0 || event.detail.display === 3,
|
||||
});
|
||||
},
|
||||
print: event => {
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
print: event.detail.print,
|
||||
});
|
||||
},
|
||||
hidden: event => {
|
||||
event.target.style.visibility = event.detail.hidden
|
||||
? "hidden"
|
||||
: "visible";
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
hidden: event.detail.hidden,
|
||||
});
|
||||
},
|
||||
focus: event => {
|
||||
setTimeout(() => event.target.focus({ preventScroll: false }), 0);
|
||||
},
|
||||
userName: event => {
|
||||
// tooltip
|
||||
event.target.title = event.detail.userName;
|
||||
},
|
||||
readonly: event => {
|
||||
if (event.detail.readonly) {
|
||||
event.target.setAttribute("readonly", "");
|
||||
} else {
|
||||
event.target.removeAttribute("readonly");
|
||||
}
|
||||
},
|
||||
required: event => {
|
||||
if (event.detail.required) {
|
||||
event.target.setAttribute("required", "");
|
||||
} else {
|
||||
event.target.removeAttribute("required");
|
||||
}
|
||||
},
|
||||
bgColor: event => {
|
||||
setColor("bgColor", "backgroundColor", event);
|
||||
},
|
||||
fillColor: event => {
|
||||
setColor("fillColor", "backgroundColor", event);
|
||||
},
|
||||
fgColor: event => {
|
||||
setColor("fgColor", "color", event);
|
||||
},
|
||||
textColor: event => {
|
||||
setColor("textColor", "color", event);
|
||||
},
|
||||
borderColor: event => {
|
||||
setColor("borderColor", "borderColor", event);
|
||||
},
|
||||
strokeColor: event => {
|
||||
setColor("strokeColor", "borderColor", event);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
_dispatchEventFromSandbox(actions, jsEvent) {
|
||||
const commonActions = this._commonActions;
|
||||
for (const name of Object.keys(jsEvent.detail)) {
|
||||
const action = actions[name] || commonActions[name];
|
||||
if (action) {
|
||||
action(jsEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setDefaultPropertiesFromJS(element) {
|
||||
if (!this.enableScripting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Some properties may have been updated thanks to JS.
|
||||
const storedData = this.annotationStorage.getRawValue(this.data.id);
|
||||
if (!storedData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const commonActions = this._commonActions;
|
||||
for (const [actionName, detail] of Object.entries(storedData)) {
|
||||
const action = commonActions[actionName];
|
||||
if (action) {
|
||||
action({ detail, target: element });
|
||||
// The action has been consumed: no need to keep it.
|
||||
delete storedData[actionName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create quadrilaterals from the annotation's quadpoints.
|
||||
*
|
||||
@ -657,7 +761,7 @@ class LinkAnnotationElement extends AnnotationElement {
|
||||
switch (field.type) {
|
||||
case "text": {
|
||||
const value = field.defaultValue || "";
|
||||
storage.setValue(id, { value, valueAsString: value });
|
||||
storage.setValue(id, { value });
|
||||
break;
|
||||
}
|
||||
case "checkbox":
|
||||
@ -794,85 +898,6 @@ class WidgetAnnotationElement extends AnnotationElement {
|
||||
? "transparent"
|
||||
: Util.makeHexColor(color[0], color[1], color[2]);
|
||||
}
|
||||
|
||||
_dispatchEventFromSandbox(actions, jsEvent) {
|
||||
const setColor = (jsName, styleName, event) => {
|
||||
const color = event.detail[jsName];
|
||||
event.target.style[styleName] = ColorConverters[`${color[0]}_HTML`](
|
||||
color.slice(1)
|
||||
);
|
||||
};
|
||||
|
||||
const commonActions = {
|
||||
display: event => {
|
||||
const hidden = event.detail.display % 2 === 1;
|
||||
event.target.style.visibility = hidden ? "hidden" : "visible";
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
hidden,
|
||||
print: event.detail.display === 0 || event.detail.display === 3,
|
||||
});
|
||||
},
|
||||
print: event => {
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
print: event.detail.print,
|
||||
});
|
||||
},
|
||||
hidden: event => {
|
||||
event.target.style.visibility = event.detail.hidden
|
||||
? "hidden"
|
||||
: "visible";
|
||||
this.annotationStorage.setValue(this.data.id, {
|
||||
hidden: event.detail.hidden,
|
||||
});
|
||||
},
|
||||
focus: event => {
|
||||
setTimeout(() => event.target.focus({ preventScroll: false }), 0);
|
||||
},
|
||||
userName: event => {
|
||||
// tooltip
|
||||
event.target.title = event.detail.userName;
|
||||
},
|
||||
readonly: event => {
|
||||
if (event.detail.readonly) {
|
||||
event.target.setAttribute("readonly", "");
|
||||
} else {
|
||||
event.target.removeAttribute("readonly");
|
||||
}
|
||||
},
|
||||
required: event => {
|
||||
if (event.detail.required) {
|
||||
event.target.setAttribute("required", "");
|
||||
} else {
|
||||
event.target.removeAttribute("required");
|
||||
}
|
||||
},
|
||||
bgColor: event => {
|
||||
setColor("bgColor", "backgroundColor", event);
|
||||
},
|
||||
fillColor: event => {
|
||||
setColor("fillColor", "backgroundColor", event);
|
||||
},
|
||||
fgColor: event => {
|
||||
setColor("fgColor", "color", event);
|
||||
},
|
||||
textColor: event => {
|
||||
setColor("textColor", "color", event);
|
||||
},
|
||||
borderColor: event => {
|
||||
setColor("borderColor", "borderColor", event);
|
||||
},
|
||||
strokeColor: event => {
|
||||
setColor("strokeColor", "borderColor", event);
|
||||
},
|
||||
};
|
||||
|
||||
for (const name of Object.keys(jsEvent.detail)) {
|
||||
const action = actions[name] || commonActions[name];
|
||||
if (action) {
|
||||
action(jsEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
@ -909,12 +934,12 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
// from parsing the elements correctly for the reference tests.
|
||||
const storedData = storage.getValue(id, {
|
||||
value: this.data.fieldValue,
|
||||
valueAsString: this.data.fieldValue,
|
||||
});
|
||||
const textContent = storedData.valueAsString || storedData.value || "";
|
||||
const textContent = storedData.formattedValue || storedData.value || "";
|
||||
const elementData = {
|
||||
userValue: null,
|
||||
formattedValue: null,
|
||||
valueOnFocus: "",
|
||||
};
|
||||
|
||||
if (this.data.multiLine) {
|
||||
@ -944,14 +969,15 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
});
|
||||
|
||||
element.addEventListener("resetform", event => {
|
||||
const defaultValue = this.data.defaultFieldValue || "";
|
||||
const defaultValue = this.data.defaultFieldValue ?? "";
|
||||
element.value = elementData.userValue = defaultValue;
|
||||
delete elementData.formattedValue;
|
||||
elementData.formattedValue = null;
|
||||
});
|
||||
|
||||
let blurListener = event => {
|
||||
if (elementData.formattedValue) {
|
||||
event.target.value = elementData.formattedValue;
|
||||
const { formattedValue } = elementData;
|
||||
if (formattedValue !== null && formattedValue !== undefined) {
|
||||
event.target.value = formattedValue;
|
||||
}
|
||||
// Reset the cursor position to the start of the field (issue 12359).
|
||||
event.target.scrollLeft = 0;
|
||||
@ -962,32 +988,33 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
if (elementData.userValue) {
|
||||
event.target.value = elementData.userValue;
|
||||
}
|
||||
elementData.valueOnFocus = event.target.value;
|
||||
});
|
||||
|
||||
element.addEventListener("updatefromsandbox", jsEvent => {
|
||||
const actions = {
|
||||
value(event) {
|
||||
elementData.userValue = event.detail.value || "";
|
||||
elementData.userValue = event.detail.value ?? "";
|
||||
storage.setValue(id, { value: elementData.userValue.toString() });
|
||||
if (!elementData.formattedValue) {
|
||||
event.target.value = elementData.userValue;
|
||||
}
|
||||
event.target.value = elementData.userValue;
|
||||
},
|
||||
valueAsString(event) {
|
||||
elementData.formattedValue = event.detail.valueAsString || "";
|
||||
if (event.target !== document.activeElement) {
|
||||
formattedValue(event) {
|
||||
const { formattedValue } = event.detail;
|
||||
elementData.formattedValue = formattedValue;
|
||||
if (
|
||||
formattedValue !== null &&
|
||||
formattedValue !== undefined &&
|
||||
event.target !== document.activeElement
|
||||
) {
|
||||
// Input hasn't the focus so display formatted string
|
||||
event.target.value = elementData.formattedValue;
|
||||
event.target.value = formattedValue;
|
||||
}
|
||||
storage.setValue(id, {
|
||||
formattedValue: elementData.formattedValue,
|
||||
formattedValue,
|
||||
});
|
||||
},
|
||||
selRange(event) {
|
||||
const [selStart, selEnd] = event.detail.selRange;
|
||||
if (selStart >= 0 && selEnd < event.target.value.length) {
|
||||
event.target.setSelectionRange(selStart, selEnd);
|
||||
}
|
||||
event.target.setSelectionRange(...event.detail.selRange);
|
||||
},
|
||||
};
|
||||
this._dispatchEventFromSandbox(actions, jsEvent);
|
||||
@ -1009,14 +1036,18 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
if (commitKey === -1) {
|
||||
return;
|
||||
}
|
||||
const { value } = event.target;
|
||||
if (elementData.valueOnFocus === value) {
|
||||
return;
|
||||
}
|
||||
// Save the entered value
|
||||
elementData.userValue = event.target.value;
|
||||
elementData.userValue = value;
|
||||
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
|
||||
source: this,
|
||||
detail: {
|
||||
id,
|
||||
name: "Keystroke",
|
||||
value: event.target.value,
|
||||
value,
|
||||
willCommit: true,
|
||||
commitKey,
|
||||
selStart: event.target.selectionStart,
|
||||
@ -1027,15 +1058,16 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
const _blurListener = blurListener;
|
||||
blurListener = null;
|
||||
element.addEventListener("blur", event => {
|
||||
elementData.userValue = event.target.value;
|
||||
if (this._mouseState.isDown) {
|
||||
const { value } = event.target;
|
||||
elementData.userValue = value;
|
||||
if (this._mouseState.isDown && elementData.valueOnFocus !== value) {
|
||||
// Focus out using the mouse: data are committed
|
||||
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
|
||||
source: this,
|
||||
detail: {
|
||||
id,
|
||||
name: "Keystroke",
|
||||
value: event.target.value,
|
||||
value,
|
||||
willCommit: true,
|
||||
commitKey: 1,
|
||||
selStart: event.target.selectionStart,
|
||||
@ -1048,19 +1080,56 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
|
||||
if (this.data.actions?.Keystroke) {
|
||||
element.addEventListener("beforeinput", event => {
|
||||
elementData.formattedValue = "";
|
||||
const { data, target } = event;
|
||||
const { value, selectionStart, selectionEnd } = target;
|
||||
|
||||
let selStart = selectionStart,
|
||||
selEnd = selectionEnd;
|
||||
|
||||
switch (event.inputType) {
|
||||
// https://rawgit.com/w3c/input-events/v1/index.html#interface-InputEvent-Attributes
|
||||
case "deleteWordBackward": {
|
||||
const match = value
|
||||
.substring(0, selectionStart)
|
||||
.match(/\w*[^\w]*$/);
|
||||
if (match) {
|
||||
selStart -= match[0].length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "deleteWordForward": {
|
||||
const match = value
|
||||
.substring(selectionStart)
|
||||
.match(/^[^\w]*\w*/);
|
||||
if (match) {
|
||||
selEnd += match[0].length;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "deleteContentBackward":
|
||||
if (selectionStart === selectionEnd) {
|
||||
selStart -= 1;
|
||||
}
|
||||
break;
|
||||
case "deleteContentForward":
|
||||
if (selectionStart === selectionEnd) {
|
||||
selEnd += 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// We handle the event ourselves.
|
||||
event.preventDefault();
|
||||
this.linkService.eventBus?.dispatch("dispatcheventinsandbox", {
|
||||
source: this,
|
||||
detail: {
|
||||
id,
|
||||
name: "Keystroke",
|
||||
value,
|
||||
change: data,
|
||||
change: data || "",
|
||||
willCommit: false,
|
||||
selStart: selectionStart,
|
||||
selEnd: selectionEnd,
|
||||
selStart,
|
||||
selEnd,
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -1104,6 +1173,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
|
||||
this._setTextStyle(element);
|
||||
this._setBackgroundColor(element);
|
||||
this._setDefaultPropertiesFromJS(element);
|
||||
|
||||
this.container.appendChild(element);
|
||||
return this.container;
|
||||
@ -1213,6 +1283,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
}
|
||||
|
||||
this._setBackgroundColor(element);
|
||||
this._setDefaultPropertiesFromJS(element);
|
||||
|
||||
this.container.appendChild(element);
|
||||
return this.container;
|
||||
@ -1300,6 +1371,7 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
}
|
||||
|
||||
this._setBackgroundColor(element);
|
||||
this._setDefaultPropertiesFromJS(element);
|
||||
|
||||
this.container.appendChild(element);
|
||||
return this.container;
|
||||
@ -1322,6 +1394,8 @@ class PushButtonWidgetAnnotationElement extends LinkAnnotationElement {
|
||||
container.title = this.data.alternativeText;
|
||||
}
|
||||
|
||||
this._setDefaultPropertiesFromJS(container);
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
@ -1534,6 +1608,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||
}
|
||||
|
||||
this._setBackgroundColor(selectElement);
|
||||
this._setDefaultPropertiesFromJS(selectElement);
|
||||
|
||||
this.container.appendChild(selectElement);
|
||||
return this.container;
|
||||
|
@ -50,6 +50,18 @@ class AnnotationStorage {
|
||||
return Object.assign(defaultValue, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value for a given key.
|
||||
*
|
||||
* @public
|
||||
* @memberof AnnotationStorage
|
||||
* @param {string} key
|
||||
* @returns {Object}
|
||||
*/
|
||||
getRawValue(key) {
|
||||
return this._storage.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value for a given key
|
||||
*
|
||||
|
@ -434,7 +434,7 @@ class App extends PDFObject {
|
||||
oDoc = null,
|
||||
oCheckbox = null
|
||||
) {
|
||||
if (typeof cMsg === "object") {
|
||||
if (cMsg && typeof cMsg === "object") {
|
||||
nType = cMsg.nType;
|
||||
cMsg = cMsg.cMsg;
|
||||
}
|
||||
@ -580,7 +580,7 @@ class App extends PDFObject {
|
||||
}
|
||||
|
||||
response(cQuestion, cTitle = "", cDefault = "", bPassword = "", cLabel = "") {
|
||||
if (typeof cQuestion === "object") {
|
||||
if (cQuestion && typeof cQuestion === "object") {
|
||||
cDefault = cQuestion.cDefault;
|
||||
cQuestion = cQuestion.cQuestion;
|
||||
}
|
||||
@ -590,7 +590,7 @@ class App extends PDFObject {
|
||||
}
|
||||
|
||||
setInterval(cExpr, nMilliseconds = 0) {
|
||||
if (typeof cExpr === "object") {
|
||||
if (cExpr && typeof cExpr === "object") {
|
||||
nMilliseconds = cExpr.nMilliseconds || 0;
|
||||
cExpr = cExpr.cExpr;
|
||||
}
|
||||
@ -609,7 +609,7 @@ class App extends PDFObject {
|
||||
}
|
||||
|
||||
setTimeOut(cExpr, nMilliseconds = 0) {
|
||||
if (typeof cExpr === "object") {
|
||||
if (cExpr && typeof cExpr === "object") {
|
||||
nMilliseconds = cExpr.nMilliseconds || 0;
|
||||
cExpr = cExpr.cExpr;
|
||||
}
|
||||
|
@ -820,8 +820,8 @@ class Doc extends PDFObject {
|
||||
/* Not implemented */
|
||||
}
|
||||
|
||||
getField(cName) {
|
||||
if (typeof cName === "object") {
|
||||
_getField(cName) {
|
||||
if (cName && typeof cName === "object") {
|
||||
cName = cName.cName;
|
||||
}
|
||||
if (typeof cName !== "string") {
|
||||
@ -859,6 +859,14 @@ class Doc extends PDFObject {
|
||||
return null;
|
||||
}
|
||||
|
||||
getField(cName) {
|
||||
const field = this._getField(cName);
|
||||
if (!field) {
|
||||
return null;
|
||||
}
|
||||
return field.wrapped;
|
||||
}
|
||||
|
||||
_getChildren(fieldName) {
|
||||
// Children of foo.bar are foo.bar.oof, foo.bar.rab
|
||||
// but not foo.bar.oof.FOO.
|
||||
@ -889,7 +897,7 @@ class Doc extends PDFObject {
|
||||
}
|
||||
|
||||
getNthFieldName(nIndex) {
|
||||
if (typeof nIndex === "object") {
|
||||
if (nIndex && typeof nIndex === "object") {
|
||||
nIndex = nIndex.nIndex;
|
||||
}
|
||||
if (typeof nIndex !== "number") {
|
||||
@ -1027,7 +1035,7 @@ class Doc extends PDFObject {
|
||||
bAnnotations = true,
|
||||
printParams = null
|
||||
) {
|
||||
if (typeof bUI === "object") {
|
||||
if (bUI && typeof bUI === "object") {
|
||||
nStart = bUI.nStart;
|
||||
nEnd = bUI.nEnd;
|
||||
bSilent = bUI.bSilent;
|
||||
@ -1103,30 +1111,52 @@ class Doc extends PDFObject {
|
||||
}
|
||||
|
||||
resetForm(aFields = null) {
|
||||
if (aFields && !Array.isArray(aFields) && typeof aFields === "object") {
|
||||
// Handle the case resetForm({ aFields: ... })
|
||||
if (aFields && typeof aFields === "object") {
|
||||
aFields = aFields.aFields;
|
||||
}
|
||||
|
||||
if (aFields && !Array.isArray(aFields)) {
|
||||
aFields = [aFields];
|
||||
}
|
||||
|
||||
let mustCalculate = false;
|
||||
let fieldsToReset;
|
||||
if (aFields) {
|
||||
fieldsToReset = [];
|
||||
for (const fieldName of aFields) {
|
||||
if (!fieldName) {
|
||||
continue;
|
||||
}
|
||||
const field = this.getField(fieldName);
|
||||
if (typeof fieldName !== "string") {
|
||||
// In Acrobat if a fieldName is not a string all the fields are reset.
|
||||
fieldsToReset = null;
|
||||
break;
|
||||
}
|
||||
const field = this._getField(fieldName);
|
||||
if (!field) {
|
||||
continue;
|
||||
}
|
||||
field.value = field.defaultValue;
|
||||
field.valueAsString = field.value;
|
||||
fieldsToReset.push(field);
|
||||
mustCalculate = true;
|
||||
}
|
||||
} else {
|
||||
mustCalculate = this._fields.size !== 0;
|
||||
for (const field of this._fields.values()) {
|
||||
field.value = field.defaultValue;
|
||||
field.valueAsString = field.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fieldsToReset) {
|
||||
fieldsToReset = this._fields.values();
|
||||
mustCalculate = this._fields.size !== 0;
|
||||
}
|
||||
|
||||
for (const field of fieldsToReset) {
|
||||
field.obj.value = field.obj.defaultValue;
|
||||
this._send({
|
||||
id: field.obj._id,
|
||||
value: field.obj.defaultValue,
|
||||
formattedValue: null,
|
||||
selRange: [0, 0],
|
||||
});
|
||||
}
|
||||
|
||||
if (mustCalculate) {
|
||||
this.calculateNow();
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ class EventDispatcher {
|
||||
this._objects = objects;
|
||||
|
||||
this._document.obj._eventDispatcher = this;
|
||||
this._isCalculating = false;
|
||||
}
|
||||
|
||||
mergeChange(event) {
|
||||
@ -129,61 +130,84 @@ class EventDispatcher {
|
||||
return;
|
||||
case "Action":
|
||||
this.runActions(source, source, event, name);
|
||||
if (this._document.obj.calculate) {
|
||||
this.runCalculate(source, event);
|
||||
}
|
||||
this.runCalculate(source, event);
|
||||
return;
|
||||
}
|
||||
|
||||
this.runActions(source, source, event, name);
|
||||
|
||||
if (name === "Keystroke") {
|
||||
if (event.rc) {
|
||||
if (event.willCommit) {
|
||||
this.runValidation(source, event);
|
||||
} else if (
|
||||
event.change !== savedChange.change ||
|
||||
if (name !== "Keystroke") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.rc) {
|
||||
if (event.willCommit) {
|
||||
this.runValidation(source, event);
|
||||
} else {
|
||||
const value = (source.obj.value = this.mergeChange(event));
|
||||
let selStart, selEnd;
|
||||
if (
|
||||
event.selStart !== savedChange.selStart ||
|
||||
event.selEnd !== savedChange.selEnd
|
||||
) {
|
||||
source.wrapped.value = this.mergeChange(event);
|
||||
// Selection has been changed by the script so apply the changes.
|
||||
selStart = event.selStart;
|
||||
selEnd = event.selEnd;
|
||||
} else {
|
||||
selEnd = selStart = savedChange.selStart + event.change.length;
|
||||
}
|
||||
} else if (!event.willCommit) {
|
||||
source.obj._send({
|
||||
id: source.obj._id,
|
||||
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],
|
||||
value,
|
||||
selRange: [selStart, selEnd],
|
||||
});
|
||||
}
|
||||
} else if (!event.willCommit) {
|
||||
source.obj._send({
|
||||
id: source.obj._id,
|
||||
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: "",
|
||||
formattedValue: null,
|
||||
selRange: [0, 0],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
runValidation(source, event) {
|
||||
const hasRan = this.runActions(source, source, event, "Validate");
|
||||
const didValidateRun = this.runActions(source, source, event, "Validate");
|
||||
if (event.rc) {
|
||||
if (hasRan) {
|
||||
source.wrapped.value = event.value;
|
||||
source.wrapped.valueAsString = event.value;
|
||||
} else {
|
||||
source.obj.value = event.value;
|
||||
source.obj.valueAsString = event.value;
|
||||
source.obj.value = event.value;
|
||||
|
||||
this.runCalculate(source, event);
|
||||
|
||||
const savedValue = (event.value = source.obj.value);
|
||||
let formattedValue = null;
|
||||
|
||||
if (this.runActions(source, source, event, "Format")) {
|
||||
formattedValue = event.value;
|
||||
}
|
||||
|
||||
if (this._document.obj.calculate) {
|
||||
this.runCalculate(source, event);
|
||||
}
|
||||
|
||||
event.value = source.obj.value;
|
||||
this.runActions(source, source, event, "Format");
|
||||
source.wrapped.valueAsString = event.value;
|
||||
source.obj._send({
|
||||
id: source.obj._id,
|
||||
value: savedValue,
|
||||
formattedValue,
|
||||
});
|
||||
event.value = savedValue;
|
||||
} else if (didValidateRun) {
|
||||
// The value is not valid.
|
||||
source.obj._send({
|
||||
id: source.obj._id,
|
||||
value: "",
|
||||
formattedValue: null,
|
||||
selRange: [0, 0],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,17 +222,42 @@ class EventDispatcher {
|
||||
}
|
||||
|
||||
calculateNow() {
|
||||
if (!this._calculationOrder) {
|
||||
// This function can be called by a JS script (doc.calculateNow()).
|
||||
// If !this._calculationOrder then there is nothing to calculate.
|
||||
// _isCalculating is here to prevent infinite recursion with calculateNow.
|
||||
// If !this._document.obj.calculate then the script doesn't want to have
|
||||
// a calculate.
|
||||
|
||||
if (
|
||||
!this._calculationOrder ||
|
||||
this._isCalculating ||
|
||||
!this._document.obj.calculate
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this._isCalculating = true;
|
||||
const first = this._calculationOrder[0];
|
||||
const source = this._objects[first];
|
||||
globalThis.event = new Event({});
|
||||
this.runCalculate(source, globalThis.event);
|
||||
|
||||
try {
|
||||
this.runCalculate(source, globalThis.event);
|
||||
} catch (error) {
|
||||
this._isCalculating = false;
|
||||
throw error;
|
||||
}
|
||||
|
||||
this._isCalculating = false;
|
||||
}
|
||||
|
||||
runCalculate(source, event) {
|
||||
if (!this._calculationOrder) {
|
||||
// _document.obj.calculate is equivalent to doc.calculate and can be
|
||||
// changed by a script to allow a future calculate or not.
|
||||
// This function is either called by calculateNow or when an action
|
||||
// is triggered (in this case we cannot be currently calculating).
|
||||
// So there are no need to check for _isCalculating because it has
|
||||
// been already done in calculateNow.
|
||||
if (!this._calculationOrder || !this._document.obj.calculate) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -218,31 +267,43 @@ class EventDispatcher {
|
||||
}
|
||||
|
||||
if (!this._document.obj.calculate) {
|
||||
// An action may have changed calculate value.
|
||||
continue;
|
||||
// An action could have changed calculate value.
|
||||
break;
|
||||
}
|
||||
|
||||
event.value = null;
|
||||
const target = this._objects[targetId];
|
||||
let savedValue = target.obj.value;
|
||||
this.runActions(source, target, event, "Calculate");
|
||||
if (!event.rc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (event.value !== null) {
|
||||
target.wrapped.value = event.value;
|
||||
// A new value has been calculated so set it.
|
||||
target.obj.value = event.value;
|
||||
}
|
||||
|
||||
event.value = target.obj.value;
|
||||
this.runActions(target, target, event, "Validate");
|
||||
if (!event.rc) {
|
||||
if (target.obj.value !== savedValue) {
|
||||
target.wrapped.value = savedValue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
event.value = target.obj.value;
|
||||
this.runActions(target, target, event, "Format");
|
||||
if (event.value !== null) {
|
||||
target.wrapped.valueAsString = event.value;
|
||||
savedValue = event.value = target.obj.value;
|
||||
let formattedValue = null;
|
||||
if (this.runActions(target, target, event, "Format")) {
|
||||
formattedValue = event.value;
|
||||
}
|
||||
|
||||
target.obj._send({
|
||||
id: target.obj._id,
|
||||
value: savedValue,
|
||||
formattedValue,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +87,6 @@ class Field extends PDFObject {
|
||||
|
||||
this._globalEval = data.globalEval;
|
||||
this._appObjects = data.appObjects;
|
||||
|
||||
this.valueAsString = data.valueAsString || this._value;
|
||||
}
|
||||
|
||||
get currentValueIndices() {
|
||||
@ -252,14 +250,11 @@ class Field extends PDFObject {
|
||||
}
|
||||
|
||||
get valueAsString() {
|
||||
if (this._valueAsString === undefined) {
|
||||
this._valueAsString = this._value ? this._value.toString() : "";
|
||||
}
|
||||
return this._valueAsString;
|
||||
return (this._value ?? "").toString();
|
||||
}
|
||||
|
||||
set valueAsString(val) {
|
||||
this._valueAsString = val ? val.toString() : "";
|
||||
set valueAsString(_) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
browseForFileToSubmit() {
|
||||
@ -376,7 +371,9 @@ class Field extends PDFObject {
|
||||
}
|
||||
|
||||
if (this._children === null) {
|
||||
this._children = this._document.obj._getChildren(this._fieldPath);
|
||||
this._children = this._document.obj
|
||||
._getChildren(this._fieldPath)
|
||||
.map(child => child.wrapped);
|
||||
}
|
||||
return this._children;
|
||||
}
|
||||
@ -481,7 +478,7 @@ class Field extends PDFObject {
|
||||
}
|
||||
|
||||
_reset() {
|
||||
this.value = this.valueAsString = this.defaultValue;
|
||||
this.value = this.defaultValue;
|
||||
}
|
||||
|
||||
_runActions(event) {
|
||||
|
@ -120,8 +120,8 @@ function initSandbox(params) {
|
||||
}
|
||||
|
||||
const wrapped = new Proxy(field, proxyHandler);
|
||||
doc._addField(name, wrapped);
|
||||
const _object = { obj: field, wrapped };
|
||||
doc._addField(name, _object);
|
||||
for (const object of objs) {
|
||||
appObjects[object.id] = _object;
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ describe("Interaction", () => {
|
||||
await page.click("[data-annotation-id='402R']");
|
||||
|
||||
await Promise.all(
|
||||
["16", "22", "19", "05", "27"].map(id =>
|
||||
["16", "22", "19", "05"].map(id =>
|
||||
page.waitForFunction(
|
||||
`document.querySelector("#\\\\34 ${id}R").value === ""`
|
||||
)
|
||||
@ -256,11 +256,14 @@ describe("Interaction", () => {
|
||||
text = await page.$eval("#\\34 05R", el => el.value);
|
||||
expect(text).toEqual("");
|
||||
|
||||
const sum = await page.$eval("#\\34 27R", el => el.value);
|
||||
expect(sum).toEqual("");
|
||||
|
||||
checked = await page.$eval("#\\34 49R", el => el.checked);
|
||||
expect(checked).toEqual(false);
|
||||
|
||||
const visibility = await page.$eval(
|
||||
"#\\34 27R",
|
||||
el => getComputedStyle(el).visibility
|
||||
);
|
||||
expect(visibility).toEqual("hidden");
|
||||
})
|
||||
);
|
||||
});
|
||||
@ -992,7 +995,7 @@ describe("Interaction", () => {
|
||||
await clearInput(page, "#\\33 0R");
|
||||
|
||||
await page.focus("#\\32 9R");
|
||||
await page.type("#\\32 9R", "12A");
|
||||
await page.type("#\\32 9R", "12A", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 9R").value !== "12A"`
|
||||
);
|
||||
@ -1001,7 +1004,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("12");
|
||||
|
||||
await page.focus("#\\32 9R");
|
||||
await page.type("#\\32 9R", "34");
|
||||
await page.type("#\\32 9R", "34", { delay: 100 });
|
||||
await page.click("[data-annotation-id='30R']");
|
||||
|
||||
await page.waitForFunction(
|
||||
@ -1012,7 +1015,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("");
|
||||
|
||||
await page.focus("#\\32 9R");
|
||||
await page.type("#\\32 9R", "12345");
|
||||
await page.type("#\\32 9R", "12345", { delay: 100 });
|
||||
await page.click("[data-annotation-id='30R']");
|
||||
|
||||
text = await page.$eval(`#\\32 9R`, el => el.value);
|
||||
@ -1049,7 +1052,7 @@ describe("Interaction", () => {
|
||||
await clearInput(page, "#\\33 0R");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "(123) 456A");
|
||||
await page.type("#\\33 0R", "(123) 456A", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\33 0R").value !== "(123) 456A"`
|
||||
);
|
||||
@ -1058,7 +1061,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("(123) 456");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "-789");
|
||||
await page.type("#\\33 0R", "-789", { delay: 100 });
|
||||
await page.click("[data-annotation-id='29R']");
|
||||
|
||||
await page.waitForFunction(
|
||||
@ -1069,7 +1072,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "(123) 456-7890");
|
||||
await page.type("#\\33 0R", "(123) 456-7890", { delay: 100 });
|
||||
await page.click("[data-annotation-id='29R']");
|
||||
|
||||
text = await page.$eval(`#\\33 0R`, el => el.value);
|
||||
@ -1108,7 +1111,7 @@ describe("Interaction", () => {
|
||||
await clearInput(page, "#\\33 0R");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "123A");
|
||||
await page.type("#\\33 0R", "123A", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\33 0R").value !== "123A"`
|
||||
);
|
||||
@ -1117,7 +1120,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("123");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "-456");
|
||||
await page.type("#\\33 0R", "-456", { delay: 100 });
|
||||
await page.click("[data-annotation-id='29R']");
|
||||
|
||||
await page.waitForFunction(
|
||||
@ -1128,7 +1131,7 @@ describe("Interaction", () => {
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("");
|
||||
|
||||
await page.focus("#\\33 0R");
|
||||
await page.type("#\\33 0R", "123-4567");
|
||||
await page.type("#\\33 0R", "123-4567", { delay: 100 });
|
||||
await page.click("[data-annotation-id='29R']");
|
||||
|
||||
text = await page.$eval(`#\\33 0R`, el => el.value);
|
||||
@ -1137,4 +1140,166 @@ describe("Interaction", () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("in issue14862.pdf", () => {
|
||||
let pages;
|
||||
|
||||
beforeAll(async () => {
|
||||
pages = await loadAndWait("issue14862.pdf", "#\\32 7R");
|
||||
pages.map(async ([, page]) => {
|
||||
page.on("dialog", async dialog => {
|
||||
await dialog.dismiss();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must convert input in uppercase", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await page.waitForFunction(
|
||||
"window.PDFViewerApplication.scriptingReady === true"
|
||||
);
|
||||
|
||||
await page.type("#\\32 7R", "Hello", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 7R").value !== "Hello"`
|
||||
);
|
||||
|
||||
let text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HELLO");
|
||||
|
||||
await page.type("#\\32 7R", " world", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 7R").value !== "HELLO world"`
|
||||
);
|
||||
|
||||
text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WORLD");
|
||||
|
||||
await page.keyboard.press("Backspace");
|
||||
await page.keyboard.press("Backspace");
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 7R").value !== "HELLO WORLD"`
|
||||
);
|
||||
|
||||
text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WOR");
|
||||
|
||||
await page.type("#\\32 7R", "12.dL", { delay: 100 });
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 7R").value !== "HELLO WOR"`
|
||||
);
|
||||
|
||||
text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HELLO WORDL");
|
||||
|
||||
await page.type("#\\32 7R", " ", { delay: 100 });
|
||||
|
||||
await page.keyboard.down("Control");
|
||||
await page.keyboard.press("Backspace");
|
||||
await page.keyboard.up("Control");
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 7R").value !== "HELLO WORDL "`
|
||||
);
|
||||
|
||||
text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HELLO ");
|
||||
|
||||
await page.$eval("#\\32 7R", el => {
|
||||
// Select LL
|
||||
el.selectionStart = 2;
|
||||
el.selectionEnd = 4;
|
||||
});
|
||||
|
||||
await page.keyboard.press("a");
|
||||
text = await page.$eval("#\\32 7R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("HEAO ");
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("must check that an infinite loop is not triggered", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await page.waitForFunction(
|
||||
"window.PDFViewerApplication.scriptingReady === true"
|
||||
);
|
||||
|
||||
await page.type("#\\32 8R", "Hello", { delay: 100 });
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 8R").value !== "123"`
|
||||
);
|
||||
|
||||
let text = await page.$eval("#\\32 8R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("Hello123");
|
||||
|
||||
// The action will trigger a calculateNow which itself
|
||||
// will trigger a resetForm (inducing a calculateNow) and a
|
||||
// calculateNow.
|
||||
await page.click("[data-annotation-id='31R']");
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 8R").value !== "Hello123"`
|
||||
);
|
||||
|
||||
// Without preventing against infinite loop the field is empty.
|
||||
text = await page.$eval("#\\32 8R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("123");
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("in issue14705.pdf", () => {
|
||||
let pages;
|
||||
|
||||
beforeAll(async () => {
|
||||
pages = await loadAndWait("issue14705.pdf", "#\\32 9R");
|
||||
pages.map(async ([, page]) => {
|
||||
page.on("dialog", async dialog => {
|
||||
await dialog.dismiss();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await closePages(pages);
|
||||
});
|
||||
|
||||
it("must check that field value is correctly updated", async () => {
|
||||
await Promise.all(
|
||||
pages.map(async ([browserName, page]) => {
|
||||
await page.waitForFunction(
|
||||
"window.PDFViewerApplication.scriptingReady === true"
|
||||
);
|
||||
|
||||
await page.type("#\\32 9R", "Hello World", { delay: 100 });
|
||||
await page.click("#\\32 7R");
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 9R").value !== "Hello World"`
|
||||
);
|
||||
|
||||
let text = await page.$eval("#\\32 9R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("checked");
|
||||
|
||||
await page.click("#\\32 7R");
|
||||
|
||||
await page.waitForFunction(
|
||||
`document.querySelector("#\\\\32 9R").value !== "checked"`
|
||||
);
|
||||
|
||||
text = await page.$eval("#\\32 9R", el => el.value);
|
||||
expect(text).withContext(`In ${browserName}`).toEqual("unchecked");
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
2
test/pdfs/.gitignore
vendored
2
test/pdfs/.gitignore
vendored
@ -520,3 +520,5 @@
|
||||
!issue14502.pdf
|
||||
!issue13211.pdf
|
||||
!issue14627.pdf
|
||||
!issue14862.pdf
|
||||
!issue14705.pdf
|
||||
|
BIN
test/pdfs/issue14705.pdf
Normal file
BIN
test/pdfs/issue14705.pdf
Normal file
Binary file not shown.
BIN
test/pdfs/issue14862.pdf
Executable file
BIN
test/pdfs/issue14862.pdf
Executable file
Binary file not shown.
@ -1320,7 +1320,7 @@ describe("api", function () {
|
||||
{
|
||||
id: "25R",
|
||||
value: "",
|
||||
defaultValue: null,
|
||||
defaultValue: "",
|
||||
multiline: false,
|
||||
password: false,
|
||||
charLimit: null,
|
||||
|
@ -89,7 +89,7 @@ describe("Scripting", function () {
|
||||
return s;
|
||||
}
|
||||
const number = 123;
|
||||
const expected = (((number - 1) * number) / 2).toString();
|
||||
const expected = ((number - 1) * number) / 2;
|
||||
const refId = getId();
|
||||
|
||||
const data = {
|
||||
@ -120,7 +120,8 @@ describe("Scripting", function () {
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
valueAsString: expected,
|
||||
value: expected,
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -406,6 +407,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
value: "hella",
|
||||
selRange: [5, 5],
|
||||
});
|
||||
});
|
||||
|
||||
@ -478,7 +480,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId1)).toEqual({
|
||||
id: refId1,
|
||||
value: "world",
|
||||
valueAsString: "world",
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -799,7 +801,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
value: "123456.789",
|
||||
valueAsString: "123456.789",
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
|
||||
@ -978,7 +980,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
value: "321",
|
||||
valueAsString: "321",
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
|
||||
@ -1076,7 +1078,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refIds[3])).toEqual({
|
||||
id: refIds[3],
|
||||
value: 1,
|
||||
valueAsString: "1",
|
||||
formattedValue: null,
|
||||
});
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
@ -1089,7 +1091,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refIds[3])).toEqual({
|
||||
id: refIds[3],
|
||||
value: 3,
|
||||
valueAsString: "3",
|
||||
formattedValue: null,
|
||||
});
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
@ -1102,7 +1104,7 @@ describe("Scripting", function () {
|
||||
expect(send_queue.get(refIds[3])).toEqual({
|
||||
id: refIds[3],
|
||||
value: 6,
|
||||
valueAsString: "6",
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1137,7 +1139,8 @@ describe("Scripting", function () {
|
||||
selStart: 0,
|
||||
selEnd: 0,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
@ -1148,7 +1151,8 @@ describe("Scripting", function () {
|
||||
selStart: 1,
|
||||
selEnd: 1,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
@ -1159,7 +1163,8 @@ describe("Scripting", function () {
|
||||
selStart: 2,
|
||||
selEnd: 2,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
@ -1187,7 +1192,8 @@ describe("Scripting", function () {
|
||||
selStart: 3,
|
||||
selEnd: 3,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
|
||||
await sandbox.dispatchEventInSandbox({
|
||||
id: refId,
|
||||
@ -1200,7 +1206,8 @@ describe("Scripting", function () {
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
expect(send_queue.get(refId)).toEqual({
|
||||
id: refId,
|
||||
valueAsString: "3F?0",
|
||||
value: "3F?0",
|
||||
formattedValue: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -1242,7 +1249,8 @@ describe("Scripting", function () {
|
||||
selStart: i,
|
||||
selEnd: i,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
value += change;
|
||||
}
|
||||
|
||||
@ -1301,7 +1309,8 @@ describe("Scripting", function () {
|
||||
selStart: i,
|
||||
selEnd: i,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
value += change;
|
||||
}
|
||||
|
||||
@ -1360,7 +1369,8 @@ describe("Scripting", function () {
|
||||
selStart: i,
|
||||
selEnd: i,
|
||||
});
|
||||
expect(send_queue.has(refId)).toEqual(false);
|
||||
expect(send_queue.has(refId)).toEqual(true);
|
||||
send_queue.delete(refId);
|
||||
value += change;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user