mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
JS -- hidden annotations must be built in case a script show them
* in some pdf, there are actions with "event.source.hidden = ..." * in order to handle visibility when printing, annotationStorage is extended to store multiple properties (value, hidden, editable, ...)
This commit is contained in:
parent
1c17e078ec
commit
b11592a756
9 changed files with 210 additions and 100 deletions
|
@ -300,7 +300,6 @@ class Annotation {
|
|||
_isViewable(flags) {
|
||||
return (
|
||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.NOVIEW)
|
||||
);
|
||||
}
|
||||
|
@ -311,11 +310,18 @@ class Annotation {
|
|||
_isPrintable(flags) {
|
||||
return (
|
||||
this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN)
|
||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE)
|
||||
);
|
||||
}
|
||||
|
||||
isHidden(annotationStorage) {
|
||||
const data = annotationStorage && annotationStorage[this.data.id];
|
||||
if (data && "hidden" in data) {
|
||||
return data.hidden;
|
||||
}
|
||||
return this._hasFlag(this.flags, AnnotationFlag.HIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
|
@ -984,7 +990,7 @@ class WidgetAnnotation extends Annotation {
|
|||
}
|
||||
|
||||
data.readOnly = this.hasFieldFlag(AnnotationFieldFlag.READONLY);
|
||||
data.hidden = this.hasFieldFlag(AnnotationFieldFlag.HIDDEN);
|
||||
data.hidden = this._hasFlag(data.annotationFlags, AnnotationFlag.HIDDEN);
|
||||
|
||||
// Hide signatures because we cannot validate them, and unset the fieldValue
|
||||
// since it's (most likely) a `Dict` which is non-serializable and will thus
|
||||
|
@ -1145,7 +1151,8 @@ class WidgetAnnotation extends Annotation {
|
|||
}
|
||||
|
||||
async save(evaluator, task, annotationStorage) {
|
||||
const value = annotationStorage[this.data.id];
|
||||
const value =
|
||||
annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
|
||||
if (value === this.data.fieldValue || value === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1229,7 +1236,8 @@ class WidgetAnnotation extends Annotation {
|
|||
if (!annotationStorage || isPassword) {
|
||||
return null;
|
||||
}
|
||||
const value = annotationStorage[this.data.id];
|
||||
const value =
|
||||
annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
|
||||
if (value === undefined) {
|
||||
// The annotation hasn't been rendered so use the appearance
|
||||
return null;
|
||||
|
@ -1712,7 +1720,9 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
if (annotationStorage) {
|
||||
const value = annotationStorage[this.data.id];
|
||||
const value =
|
||||
annotationStorage[this.data.id] &&
|
||||
annotationStorage[this.data.id].value;
|
||||
if (value === undefined) {
|
||||
return super.getOperatorList(
|
||||
evaluator,
|
||||
|
@ -1767,7 +1777,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
async _saveCheckbox(evaluator, task, annotationStorage) {
|
||||
const value = annotationStorage[this.data.id];
|
||||
const value =
|
||||
annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
|
||||
if (value === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
@ -1809,7 +1820,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
async _saveRadioButton(evaluator, task, annotationStorage) {
|
||||
const value = annotationStorage[this.data.id];
|
||||
const value =
|
||||
annotationStorage[this.data.id] && annotationStorage[this.data.id].value;
|
||||
if (value === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -347,7 +347,10 @@ class Page {
|
|||
// is resolved with the complete operator list for a single annotation.
|
||||
const opListPromises = [];
|
||||
for (const annotation of annotations) {
|
||||
if (isAnnotationRenderable(annotation, intent)) {
|
||||
if (
|
||||
isAnnotationRenderable(annotation, intent) &&
|
||||
!annotation.isHidden(annotationStorage)
|
||||
) {
|
||||
opListPromises.push(
|
||||
annotation
|
||||
.getOperatorList(
|
||||
|
|
|
@ -490,7 +490,9 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
// NOTE: We cannot set the values using `element.value` below, since it
|
||||
// prevents the AnnotationLayer rasterizer in `test/driver.js`
|
||||
// from parsing the elements correctly for the reference tests.
|
||||
const textContent = storage.getOrCreateValue(id, this.data.fieldValue);
|
||||
const textContent = storage.getOrCreateValue(id, {
|
||||
value: this.data.fieldValue,
|
||||
}).value;
|
||||
|
||||
if (this.data.multiLine) {
|
||||
element = document.createElement("textarea");
|
||||
|
@ -504,7 +506,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
element.setAttribute("id", id);
|
||||
|
||||
element.addEventListener("input", function (event) {
|
||||
storage.setValue(id, event.target.value);
|
||||
storage.setValue(id, { value: event.target.value });
|
||||
});
|
||||
|
||||
element.addEventListener("blur", function (event) {
|
||||
|
@ -631,10 +633,9 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
const storage = this.annotationStorage;
|
||||
const data = this.data;
|
||||
const id = data.id;
|
||||
const value = storage.getOrCreateValue(
|
||||
id,
|
||||
data.fieldValue && data.fieldValue !== "Off"
|
||||
);
|
||||
const value = storage.getOrCreateValue(id, {
|
||||
value: data.fieldValue && data.fieldValue !== "Off",
|
||||
}).value;
|
||||
|
||||
this.container.className = "buttonWidgetAnnotation checkBox";
|
||||
|
||||
|
@ -647,7 +648,7 @@ class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
}
|
||||
|
||||
element.addEventListener("change", function (event) {
|
||||
storage.setValue(id, event.target.checked);
|
||||
storage.setValue(id, { value: event.target.checked });
|
||||
});
|
||||
|
||||
this.container.appendChild(element);
|
||||
|
@ -673,10 +674,9 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
const storage = this.annotationStorage;
|
||||
const data = this.data;
|
||||
const id = data.id;
|
||||
const value = storage.getOrCreateValue(
|
||||
id,
|
||||
data.fieldValue === data.buttonValue
|
||||
);
|
||||
const value = storage.getOrCreateValue(id, {
|
||||
value: data.fieldValue === data.buttonValue,
|
||||
}).value;
|
||||
|
||||
const element = document.createElement("input");
|
||||
element.disabled = data.readOnly;
|
||||
|
@ -692,11 +692,11 @@ class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
if (radio !== event.target) {
|
||||
storage.setValue(
|
||||
radio.parentNode.getAttribute("data-annotation-id"),
|
||||
false
|
||||
{ value: false }
|
||||
);
|
||||
}
|
||||
}
|
||||
storage.setValue(id, event.target.checked);
|
||||
storage.setValue(id, { value: event.target.checked });
|
||||
});
|
||||
|
||||
this.container.appendChild(element);
|
||||
|
@ -753,10 +753,10 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
// two field types is implemented, we should use the same pattern as the
|
||||
// other interactive widgets where the return value of `getOrCreateValue` is
|
||||
// used and the full array of field values is stored.
|
||||
storage.getOrCreateValue(
|
||||
id,
|
||||
this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : undefined
|
||||
);
|
||||
storage.getOrCreateValue(id, {
|
||||
value:
|
||||
this.data.fieldValue.length > 0 ? this.data.fieldValue[0] : undefined,
|
||||
});
|
||||
|
||||
const selectElement = document.createElement("select");
|
||||
selectElement.disabled = this.data.readOnly;
|
||||
|
@ -784,7 +784,7 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||
selectElement.addEventListener("input", function (event) {
|
||||
const options = event.target.options;
|
||||
const value = options[options.selectedIndex].value;
|
||||
storage.setValue(id, value);
|
||||
storage.setValue(id, { value });
|
||||
});
|
||||
|
||||
this.container.appendChild(selectElement);
|
||||
|
@ -1622,6 +1622,9 @@ class AnnotationLayer {
|
|||
});
|
||||
if (element.isRenderable) {
|
||||
const rendered = element.render();
|
||||
if (data.hidden) {
|
||||
rendered.style.visibility = "hidden";
|
||||
}
|
||||
if (Array.isArray(rendered)) {
|
||||
for (const renderedElement of rendered) {
|
||||
parameters.div.appendChild(renderedElement);
|
||||
|
|
|
@ -59,10 +59,22 @@ class AnnotationStorage {
|
|||
* @param {Object} value
|
||||
*/
|
||||
setValue(key, value) {
|
||||
if (this._storage.get(key) !== value) {
|
||||
const obj = this._storage.get(key);
|
||||
let modified = false;
|
||||
if (obj !== undefined) {
|
||||
for (const [entry, val] of Object.entries(value)) {
|
||||
if (obj[entry] !== val) {
|
||||
modified = true;
|
||||
obj[entry] = val;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this._storage.set(key, value);
|
||||
modified = true;
|
||||
}
|
||||
if (modified) {
|
||||
this._setModified();
|
||||
}
|
||||
this._storage.set(key, value);
|
||||
}
|
||||
|
||||
getAll() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue