First commit: can open/save/sign/stamp PDFs
commit
3f53f343fe
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2021 Netsyms Technologies.
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
/*
|
||||
Created on : Jun 27, 2021, 7:34:10 PM
|
||||
Author : Skylar Ittner
|
||||
*/
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#page-canvas-container {
|
||||
height: 90vh;
|
||||
max-height: 90vh;
|
||||
max-width: 80vw;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#page-canvas-container .page-canvas {
|
||||
margin: 0.5em;
|
||||
box-shadow: 6px 6px 7px -1px rgba(0,0,0,0.5);
|
||||
height: 100%;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
#page-canvas-container .page-canvas.active {
|
||||
margin: 0.5em;
|
||||
box-shadow: 0px 0px 7px 0px rgba(0,255,0,0.8);
|
||||
height: 100%;
|
||||
border: 1px solid blue;
|
||||
}
|
||||
|
||||
#page-canvas-container #placementguidebox {
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
float: left;
|
||||
margin-top: -40px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#signature_pad {
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
|
||||
.signature-wrapper {
|
||||
background-color: white;
|
||||
border-radius: 5px;
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
margin: 0 auto;
|
||||
border: 1px solid rgba(0,0,0,0.5);
|
||||
/* fix bug on iOS where image sticks out right side and makes entire page scroll horiz. */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.signature-wrapper img {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.signature-wrapper canvas {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 400px;
|
||||
height: 200px;
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="400"
|
||||
height="200"
|
||||
viewBox="0 0 105.83333 52.916669"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
||||
sodipodi:docname="signature-line.svg">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.7"
|
||||
inkscape:cx="-82.70874"
|
||||
inkscape:cy="65.096693"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
fit-margin-top="50"
|
||||
fit-margin-left="30"
|
||||
fit-margin-right="30"
|
||||
fit-margin-bottom="50"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
inkscape:window-x="1920"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-25.421766,-74.750004)">
|
||||
<g
|
||||
aria-label="X"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.23333311px;line-height:100%;font-family:Ubuntu;-inkscape-font-specification:Ubuntu;letter-spacing:3.34962487px;word-spacing:0px;fill:#000000;fill-opacity:0.39303482;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="text817"
|
||||
transform="matrix(4.2854051,0,0,4.2854051,-189.27268,-367.87464)">
|
||||
<path
|
||||
d="m 53.529892,112.54762 q -0.0635,-0.127 -0.1524,-0.2794 -0.0889,-0.15663 -0.194734,-0.32173 -0.105833,-0.16933 -0.220133,-0.33443 -0.1143,-0.16934 -0.220133,-0.3175 -0.105834,0.14816 -0.220134,0.3175 -0.1143,0.1651 -0.220133,0.33443 -0.1016,0.1651 -0.194733,0.32173 -0.0889,0.1524 -0.1524,0.2794 h -0.452967 q 0.1905,-0.37253 0.440267,-0.75776 0.254,-0.38524 0.537633,-0.79164 l -0.9398,-1.3843 h 0.474133 l 0.7239,1.0922 0.715434,-1.0922 h 0.4699 l -0.922867,1.36737 q 0.287867,0.41063 0.541867,0.8001 0.254,0.38947 0.448733,0.76623 z"
|
||||
style="stroke-width:0.26458332px;fill:#000000;fill-opacity:0.39303482"
|
||||
id="path819"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.9 KiB |
@ -0,0 +1,120 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright 2021 Netsyms Technologies.
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
<title>IPENtool</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="node_modules/@fortawesome/fontawesome-free/css/all.min.css" />
|
||||
<link rel="stylesheet" href="css/main.css" />
|
||||
|
||||
<div class="modal fade" id="settingsModal" tabindex="-1" aria-labelledby="settingsModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="settingsModalLabel">Settings</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
Name: <input class="form-control" type="text" id="notary_name" />
|
||||
Location (county/residing at): <input class="form-control" type="text" id="notary_location" />
|
||||
Commission expiration: <input class="form-control" type="text" id="notary_expires" />
|
||||
Commission number: <input class="form-control" type="text" id="notary_idnumber" />
|
||||
State: <select class="form-control" id="notary_state">
|
||||
<option selected></option>
|
||||
<option value="mt">Montana</option>
|
||||
</select>
|
||||
<br>
|
||||
Stamp Preview:<br>
|
||||
<img src="" id="stamp-preview" />
|
||||
<br>
|
||||
Notary Signature:<br>
|
||||
<img src="" id="signature-preview" />
|
||||
<div class="btn btn-primary" onclick="activateNotarySignaturePad()"><i class="fas fa-signature"></i> Draw Signature</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary" onclick="saveSettingsModal()">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="signatureModal" tabindex="-1" aria-labelledby="signatureModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="signatureModalLabel">Signature Pad</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="btn btn-warning d-inline-block" onclick="resizeSignaturePadCanvas();signaturePad.clear();"><i class="fas fa-eraser"></i> Erase</div>
|
||||
<div class="btn btn-primary d-inline-block" onclick="signaturePadUndo();"><i class="fas fa-undo"></i> Undo</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="signature-wrapper">
|
||||
<img src="img/signature-line.svg" />
|
||||
<canvas id="signaturecanvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="signaturePadCallback()">Apply</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<ul class="nav nav-pills">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" onclick="addPDF()"><i class="fas fa-file-pdf"></i> Add PDF</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" onclick="savePDF()"><i class="fas fa-save"></i> Save</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" onclick="openSettingsModal()"><i class="fas fa-cog"></i> Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="btn btn-primary d-inline" onclick="pdfZoom('fitheight');"><i class="fas fa-arrows-alt-v"></i> Fit Height</div>
|
||||
<div class="btn btn-primary d-inline" onclick="pdfZoom('fitwidth');"><i class="fas fa-arrows-alt-h"></i> Fit Width</div>
|
||||
<div class="btn btn-primary d-inline" onclick="pdfZoom('out');"><i class="fas fa-search-minus"></i> Zoom Out</div>
|
||||
<div class="btn btn-primary d-inline" onclick="pdfZoom('in');"><i class="fas fa-search-plus"></i> Zoom In</div>
|
||||
<div class="btn btn-primary d-inline ms-4" onclick="activateStampDrawTool()"><i class="fas fa-stamp"></i> Stamp/Seal</div>
|
||||
<div class="btn btn-primary d-inline" onclick="activateClientSignaturePad()"><i class="fas fa-file-signature"></i> Sign (Client)</div>
|
||||
<div class="btn btn-primary d-inline" onclick="activateNotarySignatureTool()"><i class="fas fa-signature"></i> Sign (Notary)</div>
|
||||
</div>
|
||||
<div class="card-body" id="page-canvas-container">
|
||||
<canvas id="placementguidebox" width="1000" height="1000"></canvas>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
Page count: <span id="page_count"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form style="display: none; height: 0; width: 0; margin: 0; padding: 0;">
|
||||
<input type="file" id="open-file-input">
|
||||
</form>
|
||||
|
||||
<div id="svgtrimbox"></div>
|
||||
|
||||
|
||||
<script src="node_modules/jquery/dist/jquery.min.js"></script>
|
||||
<script src="node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="node_modules/pdfjs-dist/build/pdf.min.js"></script>
|
||||
<script src="node_modules/jspdf/dist/jspdf.umd.min.js"></script>
|
||||
<script src="node_modules/signature_pad/dist/signature_pad.umd.min.js"></script>
|
||||
<script src="js/svg-to-image.js"></script>
|
||||
<script src="js/util.js"></script>
|
||||
<script src="js/storage.js"></script>
|
||||
<script src="js/filesystem.js"></script>
|
||||
<script src="js/drawtools.js"></script>
|
||||
<script src="js/pdf.js"></script>
|
||||
<script src="js/main.js"></script>
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2021 Netsyms Technologies.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
var activeDrawImage;
|
||||
var signaturePadCallback = function () {};
|
||||
var clientSignatureSvg = "";
|
||||
|
||||
function getStampSvg(callback) {
|
||||
$.get("templates/stamps/" + getStorage("notary_state") + ".svg", {}, function (data) {
|
||||
data = data + "";
|
||||
data = data.replaceAll("[[[NAME]]]", getStorage("notary_name"));
|
||||
data = data.replaceAll("[[[LOCATION]]]", getStorage("notary_location"));
|
||||
data = data.replaceAll("[[[EXPIRES]]]", getStorage("notary_expires"));
|
||||
data = data.replaceAll("[[[IDNUMBER]]]", getStorage("notary_idnumber"));
|
||||
|
||||
callback(data);
|
||||
}, "text");
|
||||
}
|
||||
|
||||
function makeStampImage(callback) {
|
||||
getStampSvg(function (data) {
|
||||
svgToImage(data, function (err, image) {
|
||||
if (err) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
callback(image);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function activateStampDrawTool() {
|
||||
makeStampImage(function (image) {
|
||||
activeDrawImage = image;
|
||||
enableGuideBox(image);
|
||||
});
|
||||
}
|
||||
|
||||
function activateNotarySignatureTool() {
|
||||
if (!inStorage("notary_signature")) {
|
||||
alert("Please set a notary signature in the settings.");
|
||||
return;
|
||||
}
|
||||
svgToImage(getStorage("notary_signature"), function (err, image) {
|
||||
if (err) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
activeDrawImage = image;
|
||||
enableGuideBox(image);
|
||||
});
|
||||
}
|
||||
|
||||
function activateClientSignaturePad() {
|
||||
initSignaturePad();
|
||||
signaturePadCallback = function () {
|
||||
if (clientSignatureSvg != "" && signaturePad.isEmpty()) {
|
||||
var signature = clientSignatureSvg;
|
||||
} else {
|
||||
var signature = signaturePad.toDataURL("image/svg+xml");
|
||||
signature = signature.replace("data:image/svg+xml;base64,", "");
|
||||
signature = atob(signature);
|
||||
signature = trimAndShrinkSVG(signature);
|
||||
clientSignatureSvg = signature;
|
||||
}
|
||||
|
||||
svgToImage(signature, function (err, image) {
|
||||
if (err) {
|
||||
callback(false);
|
||||
return;
|
||||
}
|
||||
activeDrawImage = image;
|
||||
enableGuideBox(image);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function drawImageFromUrl(x, y, width, height, src, canvas) {
|
||||
var ctx = canvas.getContext("2d");
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
image.onload = () => {
|
||||
ctx.drawImage(image, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
function drawImage(x, y, width, height, image, canvas) {
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, x, y, width, height);
|
||||
}
|
||||
|
||||
$("#page-canvas-container").on("click", ".page-canvas", function (evt) {
|
||||
$("#page-canvas-container .page-canvas").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
});
|
||||
|
||||
$("#page-canvas-container").on("click", ".page-canvas.active", function (evt) {
|
||||
if (typeof activeDrawImage == "undefined") {
|
||||
return;
|
||||
}
|
||||
var canvas = $(this)[0];
|
||||
var coords = getMousePos(canvas, evt);
|
||||
|
||||
var imageWidth = (activeDrawImage.width / 96) * pdfAssumedDPI * pdfPageScale;
|
||||
var imageHeight = (activeDrawImage.height / 96) * pdfAssumedDPI * pdfPageScale;
|
||||
drawImage(coords.x, coords.y, imageWidth, imageHeight, activeDrawImage, canvas);
|
||||
});
|
||||
|
||||
|
||||
function enableGuideBox(image, scalecorrectionfactor) {
|
||||
if (typeof scalecorrectionfactor == "undefined") {
|
||||
scalecorrectionfactor = 1;
|
||||
}
|
||||
// disable first to clear contents
|
||||
disableGuideBox();
|
||||
$("#placementguidebox").css("display", "");
|
||||
// calculate size of guide image
|
||||
var pageWidthPx = $("#page-canvas-container .page-canvas")[0].getContext("2d").canvas.width;
|
||||
var pageCanvasCurrentWidthPx = $("#page-canvas-container .page-canvas").css("width").replace("px", "") * 1;
|
||||
var pageWidthInches = pageWidthPx / (pdfAssumedDPI * pdfPageScale);
|
||||
var canvasCurrentDPI = pageCanvasCurrentWidthPx / pageWidthInches;
|
||||
|
||||
var imageWidth = (image.width / (96 * scalecorrectionfactor)) * canvasCurrentDPI;
|
||||
var imageHeight = (image.height / (96 * scalecorrectionfactor)) * canvasCurrentDPI;
|
||||
|
||||
var canvas = $("#placementguidebox")[0];
|
||||
var ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, imageWidth, imageHeight);
|
||||
}
|
||||
|
||||
function disableGuideBox() {
|
||||
$("#placementguidebox").css("display", "none");
|
||||
|
||||
var context = $("#placementguidebox")[0].getContext('2d');
|
||||
context.clearRect(0, 0, $("#placementguidebox")[0].width, $("#placementguidebox")[0].height);
|
||||
}
|
||||
|
||||
$("#page-canvas-container").on("mousemove", function (evt) {
|
||||
$("#placementguidebox").css({
|
||||
left: evt.pageX,
|
||||
top: evt.pageY
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* https://stackoverflow.com/a/17130415
|
||||
* @param {type} canvas
|
||||
* @param {type} evt
|
||||
* @returns {getMousePos.pdfAnonym$1}
|
||||
*/
|
||||
function getMousePos(canvas, evt) {
|
||||
var rect = canvas.getBoundingClientRect(), // abs. size of element
|
||||
scaleX = canvas.width / rect.width, // relationship bitmap vs. element for X
|
||||
scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y
|
||||
|
||||
return {
|
||||
x: (evt.clientX - rect.left) * scaleX, // scale mouse coordinates after they have
|
||||
y: (evt.clientY - rect.top) * scaleY // been adjusted to be relative to element
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
function openFileDialog(callback) {
|
||||
$("#open-file-input").off("change");
|
||||
if (typeof callback != "undefined") {
|
||||
$("#open-file-input").on("change", function () {
|
||||
callback($("#open-file-input").val());
|
||||
});
|
||||
}
|
||||
$("#open-file-input").click();
|
||||
|
||||
}
|
||||
|
||||
function getFileAsString(path) {
|
||||
const fs = require("fs");
|
||||
return fs.readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
function getFileAsUint8Array(path) {
|
||||
const fs = require("fs");
|
||||
return fs.readFileSync(path, null);
|
||||
}
|
||||
|
||||
function writeStringToFile(path, text) {
|
||||
const fs = require("fs");
|
||||
fs.writeFileSync(path, text);
|
||||
}
|
||||
|
||||
function writeDataToFile(path, data) {
|
||||
const fs = require("fs");
|
||||
fs.writeFileSync(path, data);
|
||||
}
|
||||
|
||||
function copyFile(source, dest) {
|
||||
const fs = require("fs");
|
||||
fs.copyFileSync(source, dest);
|
||||
}
|
||||
|
||||
function getBasename(fullpath) {
|
||||
var path = require("path");
|
||||
return path.basename(fullpath);
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2021 Netsyms Technologies.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
var pdfjsLib = window['pdfjs-dist/build/pdf'];
|
||||
pdfjsLib.GlobalWorkerOptions.workerSrc = 'node_modules/pdfjs-dist/build/pdf.worker.min.js';
|
||||
|
||||
var signaturePad;
|
||||
|
||||
function setupNotaryOptions(name, location, expires, idnumber, state) {
|
||||
setStorage("notary_name", name);
|
||||
setStorage("notary_location", location);
|
||||
setStorage("notary_expires", expires);
|
||||
setStorage("notary_idnumber", idnumber);
|
||||
setStorage("notary_state", state);
|
||||
}
|
||||
|
||||
function openSettingsModal() {
|
||||
$("#settingsModal #notary_name").val(getStorage("notary_name"));
|
||||
$("#settingsModal #notary_location").val(getStorage("notary_location"));
|
||||
$("#settingsModal #notary_expires").val(getStorage("notary_expires"));
|
||||
$("#settingsModal #notary_idnumber").val(getStorage("notary_idnumber"));
|
||||
$("#settingsModal #notary_state").val(getStorage("notary_state"));
|
||||
|
||||
// show preview of stamp
|
||||
if (inStorage("notary_state")) {
|
||||
getStampSvg(function (svg) {
|
||||
$("#settingsModal #stamp-preview").attr("src", "data:image/svg+xml;base64," + btoa(svg));
|
||||
});
|
||||
}
|
||||
|
||||
// show signature
|
||||
if (inStorage("notary_signature")) {
|
||||
$("#settingsModal #signature-preview").attr("src", "data:image/svg+xml;base64," + btoa(getStorage("notary_signature")));
|
||||
}
|
||||
|
||||
new bootstrap.Modal(document.getElementById('settingsModal')).show();
|
||||
}
|
||||
|
||||
function saveSettingsModal() {
|
||||
setupNotaryOptions(
|
||||
$("#settingsModal #notary_name").val(),
|
||||
$("#settingsModal #notary_location").val(),
|
||||
$("#settingsModal #notary_expires").val(),
|
||||
$("#settingsModal #notary_idnumber").val(),
|
||||
$("#settingsModal #notary_state option:selected").val());
|
||||
// show preview of stamp
|
||||
if (inStorage("notary_state")) {
|
||||
getStampSvg(function (svg) {
|
||||
$("#settingsModal #stamp-preview").attr("src", "data:image/svg+xml;base64," + btoa(svg));
|
||||
});
|
||||
}
|
||||
// show signature
|
||||
if (inStorage("notary_signature")) {
|
||||
$("#settingsModal #signature-preview").attr("src", "data:image/svg+xml;base64," + btoa(getStorage("notary_signature")));
|
||||
}
|
||||
}
|
||||
|
||||
function initSignaturePad() {
|
||||
var canvas = document.getElementById("signaturecanvas");
|
||||
signaturePad = new SignaturePad(canvas, {
|
||||
backgroundColor: 'rgba(255, 255, 255, 0.5)',
|
||||
onBegin: function () {
|
||||
// stop page from jumping around if user starts drawing signature while a text box is focused
|
||||
$("input").blur();
|
||||
}
|
||||
});
|
||||
new bootstrap.Modal(document.getElementById('signatureModal')).show();
|
||||
|
||||
|
||||
$("#signatureModal").on("shown.bs.modal", resizeSignaturePadCanvas);
|
||||
}
|
||||
|
||||
function resizeSignaturePadCanvas() {
|
||||
var canvas = document.getElementById("signaturecanvas");
|
||||
var ratio = Math.max(window.devicePixelRatio || 1, 1);
|
||||
canvas.width = canvas.offsetWidth * ratio;
|
||||
canvas.height = canvas.offsetHeight * ratio;
|
||||
canvas.getContext("2d").scale(ratio, ratio);
|
||||
if (signaturePad != null) {
|
||||
signaturePad.clear(); // otherwise isEmpty() might return incorrect value
|
||||
}
|
||||
}
|
||||
|
||||
function signaturePadUndo() {
|
||||
var data = signaturePad.toData();
|
||||
|
||||
resizeSignaturePadCanvas();
|
||||
|
||||
if (data) {
|
||||
data.pop(); // remove the last dot or line
|
||||
signaturePad.fromData(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function activateNotarySignaturePad() {
|
||||
initSignaturePad();
|
||||
signaturePadCallback = function () {
|
||||
var signature = signaturePad.toDataURL("image/svg+xml");
|
||||
signature = signature.replace("data:image/svg+xml;base64,", "");
|
||||
signature = atob(signature);
|
||||
setStorage("notary_signature", trimAndShrinkSVG(signature));
|
||||
$("#settingsModal #signature-preview").attr("src", "data:image/svg+xml;base64," + btoa(getStorage("notary_signature")));
|
||||
};
|
||||
}
|
||||
|
||||
function trimAndShrinkSVG(svgstring) {
|
||||
var div = document.getElementById('svgtrimbox');
|
||||
div.innerHTML = svgstring;
|
||||
var svg = div.firstChild;
|
||||
var bbox = svg.getBBox();
|
||||
var viewBox = [bbox.x, bbox.y, bbox.width, bbox.height].join(" ");
|
||||
svg.setAttribute("viewBox", viewBox);
|
||||
svg.setAttribute("width", 100);
|
||||
svg.setAttribute("height", 50);
|
||||
//console.log(svg.outerHTML);
|
||||
div.innerHTML = "";
|
||||
return svg.outerHTML;
|
||||
}
|
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2021 Netsyms Technologies.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
const {jsPDF} = window.jspdf;
|
||||
|
||||
var pdfPageScale = 4;
|
||||
var pdfAssumedDPI = 72;
|
||||
var pdfDoc = null;
|
||||
var pageNumber = 0;
|
||||
|
||||
function addPDF() {
|
||||
openFileDialog(function (path) {
|
||||
var filedata = getFileAsUint8Array(path);
|
||||
|
||||
/**
|
||||
* Asynchronously downloads PDF.
|
||||
*/
|
||||
pdfjsLib.getDocument(filedata).promise.then(function (pdfDoc_) {
|
||||
pdfDoc = pdfDoc_;
|
||||
|
||||
renderAllPages(pdfDoc);
|
||||
pdfZoom("fitwidth");
|
||||
// Initial/first page rendering
|
||||
//renderPage(pageNum);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function savePDF() {
|
||||
var canvases = $("#page-canvas-container .page-canvas");
|
||||
const pdf = new jsPDF({
|
||||
unit: "in",
|
||||
compress: true
|
||||
});
|
||||
// creating a PDF creates a blank page that we don't want to use,
|
||||
// as we haven't done the calculations yet
|
||||
pdf.deletePage(1);
|
||||
for (var i = 0; i < canvases.length; i++) {
|
||||
var canvas = $("#page-canvas-container .page-canvas")[i];
|
||||
var widthpx = canvas.getContext("2d").canvas.width;
|
||||
var heightpx = canvas.getContext("2d").canvas.height;
|
||||
var pageWidthInches = widthpx / (pdfAssumedDPI * pdfPageScale);
|
||||
var pageHeightInches = heightpx / (pdfAssumedDPI * pdfPageScale);
|
||||
console.log(pageWidthInches + " x " + pageHeightInches);
|
||||
var pageFormat = [pageWidthInches, pageHeightInches];
|
||||
var pageOrientation = (pageWidthInches > pageHeightInches ? "landscape" : "portrait");
|
||||
pdf.addPage(pageFormat, pageOrientation);
|
||||
pdf.addImage($("#page-canvas-container .page-canvas")[i].toDataURL(), 0, 0, pageWidthInches, pageHeightInches);
|
||||
}
|
||||
pdf.save("signed.pdf");
|
||||
}
|
||||
|
||||
function pdfZoom(str) {
|
||||
disableGuideBox();
|
||||
var widthpx = $("#page-canvas-container .page-canvas").css("width").replace("px", "") * 1;
|
||||
var zoomstep = 100;
|
||||
console.log(widthpx);
|
||||
switch (str) {
|
||||
case "out":
|
||||
$("#page-canvas-container .page-canvas").css("height", "auto");
|
||||
widthpx -= zoomstep;
|
||||
$("#page-canvas-container .page-canvas").css("width", widthpx + "px");
|
||||
break;
|
||||
case "in":
|
||||
$("#page-canvas-container .page-canvas").css("height", "auto");
|
||||
widthpx += zoomstep;
|
||||
$("#page-canvas-container .page-canvas").css("width", widthpx + "px");
|
||||
break;
|
||||
case "fitwidth":
|
||||
$("#page-canvas-container .page-canvas").css("width", "100%");
|
||||
$("#page-canvas-container .page-canvas").css("height", "auto");
|
||||
break;
|
||||
case "fitheight":
|
||||
$("#page-canvas-container .page-canvas").css("height", "100%");
|
||||
$("#page-canvas-container .page-canvas").css("width", "auto");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getNewCanvas(pagenumber) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.id = "pdf-canvas-page-" + pagenumber;
|
||||
canvas.className = "page-canvas";
|
||||
return canvas;
|
||||
}
|
||||
|
||||
function addPage() {
|
||||
pageNumber++;
|
||||
var canvas = getNewCanvas(pageNumber);
|
||||
var prevPageCanvas = $("#page-canvas-container .page-canvas#pdf-canvas-page-" + (pageNumber - 1))[0];
|
||||
canvas.width = prevPageCanvas.getContext("2d").canvas.width;
|
||||
canvas.height = prevPageCanvas.getContext("2d").canvas.height;
|
||||
$("#page-canvas-container").append(canvas);
|
||||
}
|
||||
|
||||
function renderAllPages() {
|
||||
var startingPageNumber = pageNumber;
|
||||
var thisDocPageCount = pdfDoc.numPages;
|
||||
for (var i = 1; i <= pdfDoc.numPages; i++) {
|
||||
pdfDoc.getPage(i).then(function (page) {
|
||||
var viewport = page.getViewport({scale: pdfPageScale});
|
||||
var canvas = getNewCanvas(page.pageNumber + startingPageNumber);
|
||||
canvas.height = viewport.height;
|
||||
canvas.width = viewport.width;
|
||||
$("#page-canvas-container").append(canvas);
|
||||
|
||||
// Render PDF page into canvas context
|
||||
var renderContext = {
|
||||
canvasContext: canvas.getContext("2d"),
|
||||
viewport: viewport
|
||||
};
|
||||
|
||||
page.render(renderContext);
|
||||
});
|
||||
}
|
||||
pageNumber = pageNumber + thisDocPageCount;
|
||||
document.getElementById('page_count').textContent = pageNumber;
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Save something to persistent storage.
|
||||
* @param {string} key
|
||||
* @param {string} value non-string values are converted to strings.
|
||||
* @returns {undefined}
|
||||
*/
|
||||
function setStorage(key, value) {
|
||||
localStorage.setItem(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an item from persistent storage.
|
||||
* @param {type} key
|
||||
* @returns {DOMString}
|
||||
*/
|
||||
function getStorage(key) {
|
||||
return localStorage.getItem(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an item is in the persistent storage.
|
||||
* @param {string} key
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function inStorage(key) {
|
||||
return localStorage.getItem(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all item from persistent storage.
|
||||
* @returns {Array} [{key: "", value: ""},...]
|
||||
*/
|
||||
function getAllStorage() {
|
||||
var all = [];
|
||||
for (var key in localStorage) {
|
||||
if (localStorage.hasOwnProperty(key)) {
|
||||
all.push({
|
||||
key: key,
|
||||
value: getStorage(key)
|
||||
});
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* https://github.com/Jam3/svg-to-image
|
||||
* https://github.com/mattdesl/load-img
|
||||
*/
|
||||
function loadImage(src, opt, callback) {
|
||||
if (typeof opt === 'function') {
|
||||
callback = opt;
|
||||
opt = null;
|
||||
}
|
||||
|
||||
var el = document.createElement('img');
|
||||
var locked;
|
||||
|
||||
el.onload = function onLoaded() {
|
||||
if (locked)
|
||||
return;
|
||||
locked = true;
|
||||
|
||||
if (callback)
|
||||
callback(undefined, el);
|
||||
};
|
||||
|
||||
el.onerror = function onError() {
|
||||
if (locked)
|
||||
return;
|
||||
locked = true;
|
||||
|
||||
if (callback)
|
||||
callback(new Error('Unable to load "' + src + '"'), el);
|
||||
};
|
||||
|
||||
if (opt && opt.crossOrigin) {
|
||||
el.crossOrigin = opt.crossOrigin;
|
||||
}
|
||||
|
||||
el.src = src;
|
||||
|
||||
return el;
|
||||
}
|
||||
|
||||
function svgToImage(svg, opt, cb) {
|
||||
|
||||
if (typeof opt === 'function') {
|
||||
cb = opt
|
||||
opt = {}
|
||||
}
|
||||
cb = cb || noop
|
||||
opt = opt || {}
|
||||
|
||||
if (typeof window === 'undefined') {
|
||||
return bail('window global is undefined; not in a browser')
|
||||
}
|
||||
|
||||
var DOMURL = getURL()
|
||||
if (!DOMURL ||
|
||||
typeof DOMURL.createObjectURL !== 'function' ||
|
||||
typeof DOMURL.revokeObjectURL !== 'function') {
|
||||
return bail('browser does not support URL.createObjectURL')
|
||||
}
|
||||
|
||||
if (typeof window.Blob === 'undefined') {
|
||||
return bail('browser does not support Blob constructor')
|
||||
}
|
||||
|
||||
if (!Array.isArray(svg)) {
|
||||
svg = [svg]
|
||||
}
|
||||
|
||||
var blob
|
||||
try {
|
||||
blob = new window.Blob(svg, {
|
||||
type: 'image/svg+xml;charset=utf-8'
|
||||
})
|
||||
} catch (e) {
|
||||
return bail(e)
|
||||
}
|
||||
|
||||
var url = DOMURL.createObjectURL(blob)
|
||||
loadImage(url, opt, function (err, img) {
|
||||
DOMURL.revokeObjectURL(url)
|
||||
if (err) {
|
||||
// try again for Safari 8.0, using simple encodeURIComponent
|
||||
// this will fail with DOM content but at least it works with SVG
|
||||
var url2 = 'data:image/svg+xml,' + encodeURIComponent(svg.join(''))
|
||||
return loadImage(url2, opt, cb)
|
||||
}
|
||||
|
||||
cb(err, img)
|
||||
})
|
||||
|
||||
function getURL() {
|
||||
return window.URL ||
|
||||
window.webkitURL ||
|
||||
window.mozURL ||
|
||||
window.msURL
|
||||
}
|
||||
|
||||
function bail(msg) {
|
||||
process.nextTick(function () {
|
||||
cb(new Error(msg))
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generate a UUID.
|
||||
* From https://stackoverflow.com/a/2117523
|
||||
* @returns {String}
|
||||
*/
|
||||
function uuidv4() {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a UNIX timestamp (seconds since Jan 1 1970) and format it.
|
||||
* (Mostly) compatible with PHP's date() function.
|
||||
* @param {String} date format string, see https://www.php.net/manual/en/function.date.php
|
||||
* @param {Integer} timestamp UNIX timestamp
|
||||
* @return {String}
|
||||
*/
|
||||
function formatTimestamp(format, timestamp) {
|
||||
if (typeof timestamp == "undefined") {
|
||||
timestamp = time();
|
||||
}
|
||||
var date = new Date(timestamp * 1000);
|
||||
|
||||
var out = "";
|
||||
|
||||
var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
|
||||
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
|
||||
for (var i = 0; i < format.length; i++) {
|
||||
var c = format.charAt(i);
|
||||
// Handle backslash-escaped characters
|
||||
if (c == "\\" && i < format.length - 1) {
|
||||
out += format.charAt(i + 1);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case "d":
|
||||
var d = date.getDate();
|
||||
if (d < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += d;
|
||||
break;
|
||||
case "D":
|
||||
out += days[date.getDay()].substring(0, 3);
|
||||
break;
|
||||
case "j":
|
||||
out += date.getDate();
|
||||
break;
|
||||
case "l":
|
||||
out += days[date.getDay()];
|
||||
break;
|
||||
case "N":
|
||||
// TODO
|
||||
break;
|
||||
case "S":
|
||||
// TODO
|
||||
break;
|
||||
case "w":
|
||||
out += date.getDay();
|
||||
break;
|
||||
case "z":
|
||||
// TODO
|
||||
break;
|
||||
case "W":
|
||||
// TODO
|
||||
break;
|
||||
case "F":
|
||||
out += months[date.getMonth()];
|
||||
break;
|
||||
case "m":
|
||||
var m = date.getMonth() + 1;
|
||||
if (m < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += m;
|
||||
break;
|
||||
case "M":
|
||||
out += months[date.getMonth()].substring(0, 3);
|
||||
break;
|
||||
case "n":
|
||||
out += date.getMonth() + 1;
|
||||
break;
|
||||
case "t":
|
||||
// TODO
|
||||
break;
|
||||
case "L":
|
||||
// TODO
|
||||
break;
|
||||
case "o":
|
||||
// TODO
|
||||
break;
|
||||
case "Y":
|
||||
out += date.getFullYear();
|
||||
break;
|
||||
case "y":
|
||||
var y = (date.getFullYear() + "");
|
||||
out += y.substring(y.length - 2);
|
||||
break;
|
||||
case "a":
|
||||
if (date.getHours() < 12) {
|
||||
out += "am";
|
||||
} else {
|
||||
out += "pm";
|
||||
}
|
||||
break;
|
||||
case "A":
|
||||
if (date.getHours() < 12) {
|
||||
out += "AM";
|
||||
} else {
|
||||
out += "PM";
|
||||
}
|
||||
break;
|
||||
case "B":
|
||||
// TODO
|
||||
break;
|
||||
case "g":
|
||||
var h = date.getHours() % 12;
|
||||
if (h == 0) {
|
||||
h = 12;
|
||||
}
|
||||
out += h;
|
||||
break;
|
||||
case "G":
|
||||
out += date.getHours();
|
||||
break;
|
||||
case "h":
|
||||
var h = date.getHours() % 12;
|
||||
if (h == 0) {
|
||||
h = 12;
|
||||
}
|
||||
if (h < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += h;
|
||||
break;
|
||||
case "H":
|
||||
var h = date.getHours();
|
||||
if (h < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += h;
|
||||
break;
|
||||
case "i":
|
||||
var ii = date.getMinutes();
|
||||
if (ii < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += ii;
|
||||
break;
|
||||
case "s":
|
||||
var s = date.getSeconds();
|
||||
if (s < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += s;
|
||||
break;
|
||||
case "u":
|
||||
out += date.getMilliseconds() * 1000;
|
||||
break;
|
||||
case "v":
|
||||
out += date.getMilliseconds();
|
||||
break;
|
||||
case "e":
|
||||
// TODO
|
||||
break;
|
||||
case "I":
|
||||
// TODO
|
||||
break;
|
||||
case "O":
|
||||
var off = date.getTimezoneOffset();
|
||||
var m = off % 60;
|
||||
var h = (off - m) / 60;
|
||||
if (off >= 0) {
|
||||
out += "+";
|
||||
} else {
|
||||
out += "-";
|
||||
}
|
||||
if (h < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += h;
|
||||
if (m < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += m;
|
||||
break;
|
||||
case "P":
|
||||
var off = date.getTimezoneOffset();
|
||||
var m = off % 60;
|
||||
var h = (off - m) / 60;
|
||||
if (off >= 0) {
|
||||
out += "+";
|
||||
} else {
|
||||
out += "-";
|
||||
}
|
||||
if (h < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += h;
|
||||
out += ":";
|
||||
if (m < 10) {
|
||||
out += "0";
|
||||
}
|
||||
out += m;
|
||||
break;
|
||||
case "T":
|
||||
// TODO
|
||||
break;
|
||||
case "Z":
|
||||
out += date.getTimezoneOffset() * 60;
|
||||
break;
|
||||
case "c":
|
||||
out += formatTimestamp(timestamp, "Y-m-d\\TH:i:sP");
|
||||
break;
|
||||
case "r":
|
||||
out += formatTimestamp(timestamp, "D, j M Y G:i:s O");
|
||||
break;
|
||||
case "U":
|
||||
out += Math.round(timestamp);
|
||||
break;
|
||||
default:
|
||||
out += c;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function timestampToDateTimeString(timestamp) {
|
||||
return timestampToDateString(timestamp) + " " + timestampToTimeString(timestamp);
|
||||
}
|
||||
|
||||
function timestampToDateString(timestamp) {
|
||||
var date = new Date(timestamp * 1000);
|
||||
|
||||
return date.toLocaleDateString();
|
||||
}
|
||||
|
||||
function timestampToTimeString(timestamp) {
|
||||
var date = new Date(timestamp * 1000);
|
||||
|
||||
var pm = date.getHours() >= 12;
|
||||
var hours = date.getHours() > 12 ? date.getHours() - 12 : date.getHours();
|
||||
hours = (hours == 0 ? 12 : hours);
|
||||
var minutes = date.getMinutes();
|
||||
var time = hours + ":" + (minutes < 10 ? "0" + minutes : minutes) + " " + (pm ? "PM" : "AM");
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current UNIX timestamp in seconds.
|
||||
* @returns {Number}
|
||||
*/
|
||||
function time() {
|
||||
return Date.now() / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of seconds between now and the given timestamp.
|
||||
* @param {Number} compareto
|
||||
* @returns {Number}
|
||||
*/
|
||||
function timeDiff(compareto) {
|
||||
return time() - compareto;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
file.reference.IPENtool-public_html=public_html
|
||||
file.reference.IPENtool-test=test
|
||||
file.reference.Sources-IPENtool=.
|
||||
files.encoding=UTF-8
|
||||
project.license=mpl
|
||||
site.root.folder=${file.reference.Sources-IPENtool}
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.web.clientproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/clientside-project/1">
|
||||
<name>IPENtool</name>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
@ -0,0 +1,228 @@
|
||||
{
|
||||
"name": "IPENtool",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime-corejs3": {
|
||||
"version": "7.14.7",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz",
|
||||
"integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"core-js-pure": "^3.15.0",
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@fortawesome/fontawesome-free": {
|
||||
"version": "5.15.3",
|
||||
"resolved": "https://npm.fontawesome.com/@fortawesome/fontawesome-free/-/5.15.3/fontawesome-free-5.15.3.tgz",
|
||||
"integrity": "sha512-rFnSUN/QOtnOAgqFRooTA3H57JLDm0QEG/jPdk+tLQNL/eWd+Aok8g3qCI+Q1xuDPWpGW/i9JySpJVsq8Q0s9w=="
|
||||
},
|
||||
"@pdf-lib/standard-fonts": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@pdf-lib/standard-fonts/-/standard-fonts-1.0.0.tgz",
|
||||
"integrity": "sha512-hU30BK9IUN/su0Mn9VdlVKsWBS6GyhVfqjwl1FjZN4TxP6cCw0jP2w7V3Hf5uX7M0AZJ16vey9yE0ny7Sa59ZA==",
|
||||
"requires": {
|
||||
"pako": "^1.0.6"
|
||||
}
|
||||
},
|
||||
"@pdf-lib/upng": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@pdf-lib/upng/-/upng-1.0.1.tgz",
|
||||
"integrity": "sha512-dQK2FUMQtowVP00mtIksrlZhdFXQZPC+taih1q4CvPZ5vqdxR/LKBaFg0oAfzd1GlHZXXSPdQfzQnt+ViGvEIQ==",
|
||||
"requires": {
|
||||
"pako": "^1.0.10"
|
||||
}
|
||||
},
|
||||
"@types/raf": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz",
|
||||
"integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==",
|
||||
"optional": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg=="
|
||||
},
|
||||
"base64-arraybuffer": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.2.0.tgz",
|
||||
"integrity": "sha512-7emyCsu1/xiBXgQZrscw/8KPRT44I4Yq9Pe6EGs3aPRTsWuggML1/1DTuZUuIaJPIm1FTDUVXl4x/yW8s0kQDQ==",
|
||||
"optional": true
|
||||
},
|
||||
"bootstrap": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.0.2.tgz",
|
||||
"integrity": "sha512-1Ge963tyEQWJJ+8qtXFU6wgmAVj9gweEjibUdbmcCEYsn38tVwRk8107rk2vzt6cfQcRr3SlZ8aQBqaD8aqf+Q=="
|
||||
},
|
||||
"btoa": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz",
|
||||
"integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g=="
|
||||
},
|
||||
"canvg": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.7.tgz",
|
||||
"integrity": "sha512-4sq6iL5Q4VOXS3PL1BapiXIZItpxYyANVzsAKpTPS5oq4u3SKbGfUcbZh2gdLCQ3jWpG/y5wRkMlBBAJhXeiZA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/runtime-corejs3": "^7.9.6",
|
||||
"@types/raf": "^3.4.0",
|
||||
"raf": "^3.4.1",
|
||||
"rgbcolor": "^1.0.1",
|
||||
"stackblur-canvas": "^2.0.0",
|
||||
"svg-pathdata": "^5.0.5"
|
||||
}
|
||||
},
|
||||
"core-js": {
|
||||
"version": "3.15.2",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz",
|
||||
"integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==",
|
||||
"optional": true
|
||||
},
|
||||
"core-js-pure": {
|
||||
"version": "3.15.2",
|
||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.2.tgz",
|
||||
"integrity": "sha512-D42L7RYh1J2grW8ttxoY1+17Y4wXZeKe7uyplAI3FkNQyI5OgBIAjUfFiTPfL1rs0qLpxaabITNbjKl1Sp82tA==",
|
||||
"optional": true
|
||||
},
|
||||
"css-line-break": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-1.1.1.tgz",
|
||||
"integrity": "sha512-1feNVaM4Fyzdj4mKPIQNL2n70MmuYzAXZ1aytlROFX1JsOo070OsugwGjj7nl6jnDJWHDM8zRZswkmeYVWZJQA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"base64-arraybuffer": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"dompurify": {
|
||||
"version": "2.2.9",
|
||||
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.2.9.tgz",
|
||||
"integrity": "sha512-+9MqacuigMIZ+1+EwoEltogyWGFTJZWU3258Rupxs+2CGs4H914G9er6pZbsme/bvb5L67o2rade9n21e4RW/w==",
|
||||
"optional": true
|
||||
},
|
||||
"fflate": {
|
||||
"version": "0.4.8",
|
||||
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz",
|
||||
"integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA=="
|
||||
},
|
||||
"html2canvas": {
|
||||
"version": "1.0.0-rc.7",
|
||||
"resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.0.0-rc.7.tgz",
|
||||
"integrity": "sha512-yvPNZGejB2KOyKleZspjK/NruXVQuowu8NnV2HYG7gW7ytzl+umffbtUI62v2dCHQLDdsK6HIDtyJZ0W3neerA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"css-line-break": "1.1.1"
|
||||
}
|
||||
},
|
||||
"jquery": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
|
||||
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw=="
|
||||
},
|
||||
"jspdf": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.3.1.tgz",
|
||||
"integrity": "sha512-1vp0USP1mQi1h7NKpwxjFgQkJ5ncZvtH858aLpycUc/M+r/RpWJT8PixAU7Cw/3fPd4fpC8eB/Bj42LnsR21YQ==",
|
||||
"requires": {
|
||||
"atob": "^2.1.2",
|
||||
"btoa": "^1.2.1",
|
||||
"canvg": "^3.0.6",
|
||||
"core-js": "^3.6.0",
|
||||
"dompurify": "^2.2.0",
|
||||
"fflate": "^0.4.8",
|
||||
"html2canvas": "^1.0.0-rc.5"
|
||||
}
|
||||
},
|
||||
"konva": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/konva/-/konva-8.1.0.tgz",
|
||||
"integrity": "sha512-HkS5jB4oZlj+koSBmKWWWBOoaivnKDsEAZUkk+6xlOT+ryj5HFXkTfBZZKBS+IA0WRz3vDpko0y3LFAzuc86kA=="
|
||||
},
|
||||
"load-img": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-img/-/load-img-1.0.0.tgz",
|
||||
"integrity": "sha1-CVN0SYk8MqhwkHRkVWbExfqprCY="
|
||||
},
|
||||
"pako": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
|
||||
},
|
||||
"pdf-lib": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/pdf-lib/-/pdf-lib-1.16.0.tgz",
|
||||
"integrity": "sha512-P/1SSmElOBKrPlbc+Sn7UxikRQbzVA64+4Dh6/uczPscvq/NatP9eryoOguyBTpTnzICNiG8EnMH4Ziqp2TnFA==",
|
||||
"requires": {
|
||||
"@pdf-lib/standard-fonts": "^1.0.0",
|
||||
"@pdf-lib/upng": "^1.0.1",
|
||||
"pako": "^1.0.11",
|
||||
"tslib": "^1.11.1"
|
||||
}
|
||||
},
|
||||
"pdfjs-dist": {
|
||||
"version": "2.8.335",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.8.335.tgz",
|
||||
"integrity": "sha512-2IKw7wP1RnzzWJcpkeZwF+cKROFiQext+/WburB6cgKwt9zc8rOyDH7a3FepdcciSGs8SDs/AuWe8qVx+iI6pw=="
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"optional": true
|
||||
},
|
||||
"raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.7",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
|
||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
||||
"optional": true
|
||||
},
|
||||
"rgbcolor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
||||
"integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0=",
|
||||
"optional": true
|
||||
},
|
||||
"signature_pad": {
|
||||
"version": "3.0.0-beta.4",
|
||||
"resolved": "https://registry.npmjs.org/signature_pad/-/signature_pad-3.0.0-beta.4.tgz",
|
||||
"integrity": "sha512-cOf2NhVuTiuNqe2X/ycEmizvCDXk0DoemhsEpnkcGnA4kS5iJYTCqZ9As7tFBbsch45Q1EdX61833+6sjJ8rrw=="
|
||||
},
|
||||
"stackblur-canvas": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz",
|
||||
"integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==",
|
||||
"optional": true
|
||||
},
|
||||
"svg-pathdata": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-5.0.5.tgz",
|
||||
"integrity": "sha512-TAAvLNSE3fEhyl/Da19JWfMAdhSXTYeviXsLSoDT1UM76ADj5ndwAPX1FKQEgB/gFMPavOy6tOqfalXKUiXrow==",
|
||||
"optional": true
|
||||
},
|
||||
"svg-to-image": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/svg-to-image/-/svg-to-image-1.1.3.tgz",
|
||||
"integrity": "sha1-1v9NiDyo9+P3krQrIyixXL4vsPM=",
|
||||
"requires": {
|
||||
"load-img": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "IPENtool",
|
||||
"main": "index.html",
|
||||
"version": "1.0.0",
|
||||
"keywords": [
|
||||
"util",
|
||||
"functional",
|
||||
"server",
|
||||
"client",
|
||||
"browser"
|
||||
],
|
||||
"author": "Skylar Ittner",
|
||||
"contributors": [],
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"bootstrap": "^5.0.2",
|
||||
"jquery": "^3.6.0",
|
||||
"jspdf": "^2.3.1",
|
||||
"konva": "^8.1.0",
|
||||
"pdf-lib": "^1.16.0",
|
||||
"pdfjs-dist": "^2.8.335",
|
||||
"signature_pad": "^3.0.0-beta.4",
|
||||
"svg-to-image": "^1.1.3"
|
||||
}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="2.5in" height="1in" version="1.1" viewBox="0 0 63.5 25.4" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g transform="translate(0 -271.6)"><rect x=".24462" y="271.84" width="63.011" height="24.911" fill="none" stroke="#000" stroke-width=".48924"/><text x="44.025459" y="275.92871" fill="#000000" font-family="'Ubuntu Condensed'" font-size="3.5278px" letter-spacing=".052917px" stroke-width=".26458px" text-align="center" text-anchor="middle" word-spacing="0px" style="line-height:89.99999762%" xml:space="preserve"><tspan x="44.051918" y="275.92871" text-align="center" style="line-height:89.99999762%">[[[NAME]]]</tspan><tspan x="44.051918" y="279.1037" text-align="center" style="line-height:89.99999762%">Notary Public for the</tspan><tspan x="44.051918" y="282.27872" text-align="center" style="line-height:89.99999762%">State of Montana</tspan><tspan x="44.051918" y="285.4537" text-align="center" style="line-height:89.99999762%">Residing at</tspan><tspan x="44.051918" y="288.62872" text-align="center" style="line-height:89.99999762%">[[[LOCATION]]]</tspan><tspan x="44.051918" y="291.80371" text-align="center" style="line-height:89.99999762%">My Commission Expires</tspan><tspan x="44.051918" y="294.9787" text-align="center" style="line-height:89.99999762%">[[[EXPIRES]]]</tspan></text><g><g transform="translate(1.2654e-7 -.016449)" fill="#000000" font-family="Ubuntu" letter-spacing=".052917px" stroke-width=".26458px" text-anchor="middle" word-spacing="0px"><text x="13.02184" y="287.62936" font-size="3.5278px" text-align="center" style="line-height:100%" xml:space="preserve"><tspan x="13.048299" y="287.62936" font-size="3.5278px" letter-spacing=".052917px" stroke-width=".26458px" text-align="center" text-anchor="middle">SEAL</tspan></text><text x="12.974876" y="282.86688" font-size="2.4694px" text-align="center" style="line-height:100%" xml:space="preserve"><tspan x="13.001334" y="282.86688" font-size="2.4694px" letter-spacing=".052917px" stroke-width=".26458px" text-align="center" text-anchor="middle">Notarial</tspan></text></g><circle cx="13.051" cy="284.3" r="7.362" fill="none" stroke="#000" stroke-dasharray="0.254,0.254" stroke-width=".254"/></g><g fill="none" stroke="#000"><circle cx="13.051" cy="284.3" r="11.139" stroke-width=".254"/><circle cx="13.051" cy="284.3" r="11.301" stroke-dasharray="0.762,0.381" stroke-width=".381"/></g><path id="b" d="m4.3999 289.29a9.9893 9.9893 0 0 0 8.651 4.9947 9.9893 9.9893 0 0 0 8.651-4.9947" fill="none"/><text transform="rotate(-1.5305 13.012 288.47)" fill="#000000" font-family="'Ubuntu Condensed'" font-size="2.8222px" letter-spacing=".13229px" stroke-width=".26458px" text-align="center" text-anchor="middle" word-spacing="0px" style="line-height:100%" xml:space="preserve"><textPath startOffset="50%" xlink:href="#b"><tspan font-family="'Ubuntu Condensed'" font-size="2.8222px" letter-spacing=".13229px" stroke-width=".26458px" text-align="center" text-anchor="middle">State of Montana</tspan></textPath></text><text transform="rotate(1.0275 -16.556 287.48)" x="0.28497145" fill="#000000" font-family="'Ubuntu Condensed'" font-size="2.8222px" letter-spacing=".13229px" stroke-width=".26458px" text-align="center" text-anchor="middle" word-spacing="0px" style="line-height:100%" xml:space="preserve"><textPath startOffset="50%" xlink:href="#a"><tspan font-family="'Ubuntu Condensed'" font-size="2.8222px" letter-spacing=".13229px" stroke-width=".26458px" text-align="center" text-anchor="middle">[[[NAME]]]</tspan></textPath></text><path id="a" d="m4.9972 280.6a9.2996 10.003 0 0 1 8.0537-5.0017 9.2996 10.003 0 0 1 8.0537 5.0017" fill="none"/><g transform="translate(.064683 .27)" stroke="#000" stroke-width=".254"><path transform="matrix(.60047 -.042277 .042277 .60047 -3.9596 113.82)" d="m-5.6196 282.72-0.77787 0.6826 0.12132 1.0278-0.88957-0.52886-0.93997 0.43298 0.22809-1.0094-0.70226-0.76017 1.0305-0.095 0.50595-0.90279 0.40882 0.95073z"/><path transform="matrix(.60047 -.042277 .042277 .60047 14.561 113.82)" d="m-5.6196 282.72-0.77787 0.6826 0.12132 1.0278-0.88957-0.52886-0.93997 0.43298 0.22809-1.0094-0.70226-0.76017 1.0305-0.095 0.50595-0.90279 0.40882 0.95073z"/></g></g></svg>
|
After Width: | Height: | Size: 4.2 KiB |
Loading…
Reference in New Issue