confirm if leaving a modified form without saving

This commit is contained in:
Aki Sasaki 2020-08-18 13:50:23 -07:00
parent 965d20db2a
commit 83365a3756
4 changed files with 94 additions and 6 deletions

View File

@ -19,6 +19,14 @@
class AnnotationStorage { class AnnotationStorage {
constructor() { constructor() {
this._storage = new Map(); this._storage = new Map();
this._modified = false;
// Callbacks to signal when the modification state is set or reset.
// This is used by the viewer to only bind on `beforeunload` if forms
// are actually edited to prevent doing so unconditionally since that
// can have undesirable efffects.
this.onSetModified = null;
this.onResetModified = null;
} }
/** /**
@ -49,6 +57,9 @@ class AnnotationStorage {
* @param {Object} value * @param {Object} value
*/ */
setValue(key, value) { setValue(key, value) {
if (this._storage.get(key) !== value) {
this.setModified();
}
this._storage.set(key, value); this._storage.set(key, value);
} }
@ -62,6 +73,24 @@ class AnnotationStorage {
get size() { get size() {
return this._storage.size; return this._storage.size;
} }
setModified() {
if (!this._modified) {
this._modified = true;
if (typeof this.onSetModified === "function") {
this.onSetModified();
}
}
}
resetModified() {
if (this._modified) {
this._modified = false;
if (typeof this.onResetModified === "function") {
this.onResetModified();
}
}
}
} }
export { AnnotationStorage }; export { AnnotationStorage };

View File

@ -2536,12 +2536,16 @@ class WorkerTransport {
} }
saveDocument(annotationStorage) { saveDocument(annotationStorage) {
return this.messageHandler.sendWithPromise("SaveDocument", { return this.messageHandler
numPages: this._numPages, .sendWithPromise("SaveDocument", {
annotationStorage: numPages: this._numPages,
(annotationStorage && annotationStorage.getAll()) || null, annotationStorage:
filename: this._fullReader.filename, (annotationStorage && annotationStorage.getAll()) || null,
}); filename: this._fullReader.filename,
})
.finally(() => {
annotationStorage.resetModified();
});
} }
getDestinations() { getDestinations() {

View File

@ -38,5 +38,48 @@ describe("AnnotationStorage", function () {
expect(value).toEqual("an other string"); expect(value).toEqual("an other string");
done(); done();
}); });
it("should call onSetModified() if value is changed", function (done) {
const annotationStorage = new AnnotationStorage();
let called = false;
const callback = function () {
called = true;
};
annotationStorage.onSetModified = callback;
annotationStorage.getOrCreateValue("asdf", "original");
expect(called).toBe(false);
// not changing value
annotationStorage.setValue("asdf", "original");
expect(called).toBe(false);
// changing value
annotationStorage.setValue("asdf", "modified");
expect(called).toBe(true);
done();
});
});
describe("ResetModified", function () {
it("should call onResetModified() if set", function (done) {
const annotationStorage = new AnnotationStorage();
let called = false;
const callback = function () {
called = true;
};
annotationStorage.onResetModified = callback;
annotationStorage.getOrCreateValue("asdf", "original");
// not changing value
annotationStorage.setValue("asdf", "original");
annotationStorage.resetModified();
expect(called).toBe(false);
// changing value
annotationStorage.setValue("asdf", "modified");
annotationStorage.resetModified();
expect(called).toBe(true);
done();
});
}); });
}); });

View File

@ -127,6 +127,12 @@ function isSameScale(oldScale, newScale) {
return false; return false;
} }
function beforeUnload(evt) {
evt.preventDefault();
evt.returnValue = "";
return false;
}
/** /**
* Simple viewer control to display PDF content/pages. * Simple viewer control to display PDF content/pages.
* @implements {IRenderableView} * @implements {IRenderableView}
@ -436,6 +442,12 @@ class BaseViewer {
const firstPagePromise = pdfDocument.getPage(1); const firstPagePromise = pdfDocument.getPage(1);
const annotationStorage = pdfDocument.annotationStorage; const annotationStorage = pdfDocument.annotationStorage;
annotationStorage.onSetModified = function () {
window.addEventListener("beforeunload", beforeUnload);
};
annotationStorage.onResetModified = function () {
window.removeEventListener("beforeunload", beforeUnload);
};
this._pagesCapability.promise.then(() => { this._pagesCapability.promise.then(() => {
this.eventBus.dispatch("pagesloaded", { this.eventBus.dispatch("pagesloaded", {