window.onload = function() { const viewer = new DsPdfViewer("#viewer", getViewerOptions()); configureViewerUI(viewer); viewer.open("/document-solutions/javascript-pdf-viewer/demos/product-bundles/assets/pdf/sign-pdf-in-order.pdf"); }
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Sign PDF in order</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="./src/styles.css"> <script src="/document-solutions/javascript-pdf-viewer/demos/product-bundles/build/dspdfviewer.js"></script> <script src="/document-solutions/javascript-pdf-viewer/demos/product-bundles/build/wasmSupportApi.js"></script> <script src="/document-solutions/javascript-pdf-viewer/demos/resource/js/init.js"></script> <script src="./src/app.js"></script> <script src="./src/config.js"></script> </head> <body> <div id="viewer"></div> </body> </html>
#viewer { height: 100%; }
// exported global methods: var getViewerOptions, configureViewerUI; (function () { // Graphical signature locations. // Note that the { x, y } origin is at the bottom left. var graphicalSignatureLocationsBottomLeft = { // The key is the name of the PDF file in lower case without extension. "sign-pdf-in-order": [ { pageIndex: 0, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 0, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" }, { pageIndex: 1, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 1, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" }, { pageIndex: 2, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 2, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" }, { pageIndex: 3, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 3, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" }, { pageIndex: 4, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 4, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" }, { pageIndex: 5, x: 187, y: 73, w: 80, h: 20, title: "Buyer" }, { pageIndex: 5, x: 420, y: 73, w: 80, h: 20, title: "Seller", color: "#1234dd" } ] }; // Parameters for the "sign date" labels const signDateLabelParams = { // x offset from the position of the graphical signature offset_x: 101, // y offset from the position of the graphical signature offset_y: 0, // label width w: 58, // label height h: 14 } getViewerOptions = function getViewerOptions() { return { supportApi: { apiUrl: window.top.SUPPORTAPI_URL, // e.g. "http://localhost:5004/api/pdf-viewer"; token: window.top.SUPPORTAPI_TOKEN, // e.g. "support-api-demo-net-core-token"; webSocketUrl: false }, restoreViewStateOnLoad: false }; } configureViewerUI = function (viewer) { viewer.addDefaultPanels(); viewer.addAnnotationEditorPanel(); viewer.onAfterOpen.register(function () { populateSignature(viewer); }); } async function populateSignature(viewer) { viewer.__onSignatureLinkEvent = onSignatureLinkEvent; const locationsBottomLeft = graphicalSignatureLocationsBottomLeft[viewer.fileName.toLowerCase().replace(".pdf", "")]; if (locationsBottomLeft) { for (let i = 0; i < locationsBottomLeft.length; i++) { const locationInfo = locationsBottomLeft[i]; const pageIndex = parseInt(locationInfo.pageIndex); const signTitle = locationInfo.title; const rect = [locationInfo.x, locationInfo.y, locationInfo.x + locationInfo.w, locationInfo.y + locationInfo.h]; const signUiId = "signui_" + i; const freeTextLabel = { annotationType: 3, // AnnotationTypeCode.FREETEXT subject: signUiId, borderStyle: { width: 1, style: 2 }, fontSize: 6, appearanceColor: "#fff59d", color: locationInfo.color || "#f44336", contents: "Sign Here", textAlignment: 1, rect: [rect[0], rect[3] - 12, rect[0] + 35, rect[3]] }; await viewer.addAnnotation(pageIndex, freeTextLabel, { skipPageRefresh: true }); const viewerSelector = "#" + viewer.hostElement.id; const linkAnnotation = { annotationType: 2, // AnnotationTypeCode.LINK subject: signUiId, linkType: "js", borderStyle: { width: 0, style: 5 }, color: "#2196f3", jsAction: `if(app.viewerType == 'DsPdfViewer') { var viewer = DsPdfViewer.findControl("${viewerSelector}"); viewer.__onSignatureLinkEvent(viewer, ${pageIndex}, "${signTitle}", "${signUiId}", ${rect[0]}, ${rect[1]}, ${(rect[2] - rect[0])}, ${(rect[3] - rect[1])}); }`, rect: rect, title: signTitle }; await viewer.addAnnotation(pageIndex, linkAnnotation, { skipPageRefresh: true }); } viewer.repaint(); } } function onSignatureLinkEvent(viewer, pageIndex, signTitle, signId, x, y, w, h) { viewer.showSignTool({ subject: "AddGraphicalSignature", tabs: ["Type", "Draw"], dialogLocation: "center", pageIndex: pageIndex, title: signTitle, location: { x: x, y: y }, canvasSize: { width: w * 5, height: h * 5 }, destinationScale: 1 / 5, convertToContent: true, afterAdd: function (result) { // remove current Sign UI and scroll to next one: removeSignature(viewer, signId).then(function () { viewer.addAnnotation(pageIndex, { annotationType: 3, borderStyle: { width: 0 }, fontSize: 10, contents: new Date().toLocaleDateString("en-US"), rect: [x + signDateLabelParams.offset_x, y + signDateLabelParams.offset_y, x + signDateLabelParams.offset_x + signDateLabelParams.w, y + signDateLabelParams.offset_y + signDateLabelParams.h], convertToContent: true }, { skipPageRefresh: false }).then(function () { scrollToNextSignature(viewer, signTitle); }); }); } }); } async function removeSignature(viewer, signId) { const annotations = await viewer.findAnnotations(signId, { findField: "subject", findAll: true }); for (let data of annotations) { await viewer.removeAnnotation(data.pageIndex, data.annotation.id); } }; async function scrollToNextSignature(viewer, signTitle) { const linkAnnotations = await viewer.findAnnotations(2, { findField: "annotationType", findAll: true }); const data = linkAnnotations.find((el) => el.annotation.title === signTitle) || linkAnnotations[0]; if(data) { viewer.scrollAnnotationIntoView(data.pageIndex, data.annotation, "smooth"); } else { alert("The document is fully signed."); } } })();