let __elementIndex = 0; function generateId(envelopeId, receiverId, annotationType) { return `${envelopeId}#${receiverId}#${__elementIndex++}#${annotationType}`; } async function createAnnotations(document, envelopeId, receiverId) { const signatures = []; for (let element of document.elements) { const annotParams = await getAnnotationParams(element.left, element.top); const page = element.page - 1 //#region signatures const id = generateId(envelopeId, receiverId, 'signature'); const annotation = new PSPDFKit.Annotations.WidgetAnnotation({ id: id, pageIndex: page, formFieldName: id, backgroundColor: PSPDFKit.Color.LIGHT_YELLOW, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.signature), }) const formField = new PSPDFKit.FormFields.SignatureFormField({ name: id, annotationIds: PSPDFKit.Immutable.List([annotation.id]), }) //#endregion //#region position const id_position = generateId(envelopeId, receiverId, 'position'); const annotation_position = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_position, pageIndex: page, formFieldName: id_position, backgroundColor: PSPDFKit.Color.DarkBlue, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.position), fontSize: 8 }) const formFieldPosition = new PSPDFKit.FormFields.TextFormField({ name: id_position, annotationIds: PSPDFKit.Immutable.List([annotation_position.id]), value: "", readOnly: false }) //#endregion //#region city const id_city = generateId(envelopeId, receiverId, 'city'); const annotation_city = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_city, pageIndex: page, formFieldName: id_city, backgroundColor: PSPDFKit.Color.DarkBlue, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.city), fontSize: 8 }) const formFieldCity = new PSPDFKit.FormFields.TextFormField({ name: id_city, annotationIds: PSPDFKit.Immutable.List([annotation_city.id]), value: "", readOnly: false }) //#endregion //#region date const id_date = generateId(envelopeId, receiverId, 'date'); const annotation_date = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_date, pageIndex: page, formFieldName: id_date, backgroundColor: PSPDFKit.Color.DarkBlue, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.date), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, isBold: true, required: true }) const formFieldDate = new PSPDFKit.FormFields.TextFormField({ name: id_date, annotationIds: PSPDFKit.Immutable.List([annotation_date.id]), value: detailedCurrentDate(), readOnly: true }) //#endregion this.markFieldAsRequired(formFieldCity); this.markFieldAsCity(formFieldCity); //#region date label const id_date_label = generateId(envelopeId, receiverId, 'date_label'); const annotation_date_label = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_date_label, pageIndex: page, formFieldName: id_date_label, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.datelabel), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, isBold: true, required: true }) const formFieldDateLabel = new PSPDFKit.FormFields.TextFormField({ name: id_date_label, annotationIds: PSPDFKit.Immutable.List([annotation_date_label.id]), value: "Date", readOnly: true }) //#endregion //#region city label const id_city_label = generateId(envelopeId, receiverId, 'city_label'); const annotation_city_label = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_city_label, pageIndex: page, formFieldName: id_city_label, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.citylabel), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, isBold: true, }) const formFieldCityLabel = new PSPDFKit.FormFields.TextFormField({ name: id_city_label, annotationIds: PSPDFKit.Immutable.List([annotation_city_label.id]), value: "Ort", readOnly: true, color: PSPDFKit.Color.BLACK }) //#endregion //#region position label const id_position_label = generateId(envelopeId, receiverId, 'position_label'); const annotation_position_label = new PSPDFKit.Annotations.WidgetAnnotation({ id: id_position_label, pageIndex: page, formFieldName: id_position_label, blendMode: 'normal', boundingBox: new PSPDFKit.Geometry.Rect(annotParams.positionlabel), fontSize: 8, backgroundColor: PSPDFKit.Color.TRANSPARENT, fontColor: PSPDFKit.Color.Black, isBold: true, }) const formFieldPositionLabel = new PSPDFKit.FormFields.TextFormField({ name: id_position_label, annotationIds: PSPDFKit.Immutable.List([annotation_position_label.id]), value: "Position", readOnly: true }) //#endregion signatures.push(annotation) signatures.push(formField) signatures.push(annotation_date) signatures.push(formFieldDate) signatures.push(annotation_city) signatures.push(formFieldCity) signatures.push(annotation_position) signatures.push(formFieldPosition) signatures.push(annotation_date_label) signatures.push(formFieldDateLabel) signatures.push(annotation_city_label) signatures.push(formFieldCityLabel) signatures.push(annotation_position_label) signatures.push(formFieldPositionLabel) } return signatures; } async function getAnnotations(instance) { const array = await Promise.all( Array.from({ length: instance.totalPageCount }).map((_, pageIndex) => instance.getAnnotations(pageIndex) ) ) return array.flatMap((annotations) => annotations.reduce((acc, annotation) => acc.concat(annotation), []) ) } async function deleteAnnotations(instance) { const allAnnotations = await getAnnotations(instance) const pageAnnotations = allAnnotations.filter(isSignature) //deleting all Annotations return await instance.delete(pageAnnotations) } async function validateAnnotations(instance) { const allAnnotations = await getAnnotations(instance) const pageAnnotations = allAnnotations .map((annotation) => { return annotation }) return true } function isSignature(annotation) { return !!annotation.isSignature || annotation.description == 'FRAME' } function createImageAnnotation(boundingBox, pageIndex, imageAttachmentId, envelopeId, receiverId, annotationType) { const frameAnnotation = new PSPDFKit.Annotations.ImageAnnotation({ id: generateId(envelopeId, receiverId, annotationType), pageIndex: pageIndex, isSignature: false, readOnly: true, locked: true, lockedContents: true, contentType: 'image/png', imageAttachmentId, description: 'FRAME', boundingBox: boundingBox, }) return frameAnnotation } async function createAnnotationFrameBlob(receiverName, receiverSignature, timestamp, width, height) { Comp.SignatureProgress.SignedCount += 1; const canvas = document.createElement('canvas') const scale = 4 const fontSize = 10 canvas.width = width * scale canvas.height = height * scale const ctx = canvas.getContext('2d') // This supposedly makes the lines and text less blurry // See: https://stackoverflow.com/questions/8696631/canvas-drawings-like-lines-are-blurry ctx.translate(0.5, 0.5) // This also should make the lines and text less blurry ctx.textRendering = "geometricPrecision" const date = timestamp const dateString = date.toLocaleString('de-DE') const signatureLength = 100 * scale const signatureString = receiverSignature.substring(0, 15) + "…" ctx.beginPath() ctx.moveTo(30 * scale, 10 * scale) ctx.lineTo(signatureLength, 10 * scale) ctx.moveTo(30 * scale, 10 * scale) ctx.arcTo(10 * scale, 10 * scale, 10 * scale, 30 * scale, 20 * scale) ctx.moveTo(10 * scale, 30 * scale) ctx.arcTo(10 * scale, 50 * scale, 30 * scale, 50 * scale, 20 * scale) ctx.moveTo(30 * scale, 50 * scale) ctx.lineTo(signatureLength, 50 * scale) ctx.strokeStyle = 'darkblue' ctx.stroke() ctx.fillStyle = 'black' ctx.font = `${fontSize * scale}px sans-serif` ctx.fillText('Signed by', 15 * scale, 10 * scale) ctx.fillText(receiverName, 15 * scale, 60 * scale) ctx.fillText(signatureString, 15 * scale, 70 * scale) return new Promise((resolve) => { canvas.toBlob((blob) => { const url = URL.createObjectURL(blob) resolve(url) }) }) } //required requiredFieldNames = new Array() function markFieldAsRequired(formField) { requiredFieldNames.push(formField.name) } function isFieldRequired(formField) { return requiredFieldNames.includes(formField.name) } //city cityFieldNames = new Array() function markFieldAsCity(formField) { cityFieldNames.push(formField.name) } function isCityField(formField) { return cityFieldNames.includes(formField.name) }