diff --git a/src/index.html b/src/index.html index be5f53f..f6bfccd 100644 --- a/src/index.html +++ b/src/index.html @@ -322,5 +322,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. + + + + \ No newline at end of file diff --git a/src/js/drawtools.js b/src/js/drawtools.js index 12f10fa..2eb2a07 100644 --- a/src/js/drawtools.js +++ b/src/js/drawtools.js @@ -250,6 +250,20 @@ function getMousePos(canvas, evt) { } } +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; +} + /** * Returns true if drawing tools should be available (i.e. there's a document to draw on) * @returns {Boolean} diff --git a/src/js/events.js b/src/js/events.js new file mode 100644 index 0000000..04894c3 --- /dev/null +++ b/src/js/events.js @@ -0,0 +1,38 @@ +/* + * 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/. + */ + + + +$("body").on("input change paste", "#notaryProfileSettings input,#notaryProfileSettings select", function () { + getStampSvgWithValues({ + name: $("#settingsModal #notary_name").val(), + location: $("#settingsModal #notary_location").val(), + expires: $("#settingsModal #notary_expires").val(), + idnumber: $("#settingsModal #notary_idnumber").val(), + state: $("#settingsModal #notary_state option:selected").val() + }, function (svg) { + $("#settingsModal #stamp-preview").attr("src", "data:image/svg+xml;base64," + btoa(svg)); + }); +}); + +$("body").on("input change paste", "#appOptionsSettings select", function () { + setAppTheme($("#appOptionsSettings #color_theme option:selected").val()); + setButtonSize($("#appOptionsSettings #button_size option:selected").val()); +}); + + +$("#passwordModal").on("shown.bs.modal", function () { + $("#passwordModalInput").focus(); +}); + +$(".modal").on("keydown", function (e) { + if (e.keyCode == 13) { + // Prevent overlapping modals from all getting clicked + e.stopPropagation(); + $(this).find(".btn-default").first().click(); + } +}); \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index 9f83975..c9620ad 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -9,202 +9,6 @@ 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")); - - $("#settingsModal #color_theme").val(inStorage("color_theme") ? getStorage("color_theme") : "purple"); - $("#settingsModal #button_size").val(getStorage("button_size") ? getStorage("button_size") : "sm"); - // 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"))); - } - - setStorage("color_theme", $("#appOptionsSettings #color_theme option:selected").val()); - setAppTheme(getStorage("color_theme")); - setStorage("button_size", $("#appOptionsSettings #button_size option:selected").val()); - setButtonSize(getStorage("button_size")); - showToast(" Settings saved."); -} - -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 signatureRemoteModalOpen() { - var url = getSignatureServerUrl(); - $("#signatureRemoteUrlLabel").text(url); - $("#signatureRemoteQRCode").html(""); - new QRCode(document.getElementById("signatureRemoteQRCode"), url); - new bootstrap.Modal(document.getElementById('signatureRemoteModal')).show(); -} - - -function handleRemoteSignatureData(data) { - if (!$("#signatureModal").hasClass("show")) { - return; - } - var canvas = document.getElementById("signaturecanvas"); - signaturePad.fromData(scaleSignatureData(data, canvas.width, canvas.height)); -} - -function scaleSignatureData(data, width, height) { - // Get width and height of data - // Get the minimum positions too for adding a bit of margin - var oldwidth = 0; - var oldheight = 0; - var oldminX = 999999999; - var oldminY = 999999999; - for (var i = 0; i < data.length; i++) { - for (var j = 0; j < data[i].points.length; j++) { - oldwidth = Math.max(data[i].points[j].x, oldwidth); - oldheight = Math.max(data[i].points[j].y, oldheight); - oldminX = Math.min(data[i].points[j].x, oldminX); - oldminY = Math.min(data[i].points[j].y, oldminY); - } - } - var xPad = oldminX / 2; - var yPad = oldminY / 2; - // Calculate scale ratios - var scaleX = (oldwidth + xPad * 2) / width; - var scaleY = (oldheight + yPad * 2) / height; - // Pick the largest scale ratio and use only that one so it maintains aspect ratio - var scale = Math.max(scaleX, scaleY); - // Loop over the old data and scale the points into a new signature data object - var newdata = []; - for (var i = 0; i < data.length; i++) { - var newpoints = []; - for (var j = 0; j < data[i].points.length; j++) { - newpoints.push({ - time: data[i].points[j].time, - x: (data[i].points[j].x + xPad) / scale, - y: (data[i].points[j].y + yPad) / scale - }); - } - newdata.push({ - color: data[i].color, - points: newpoints - }); - } - return newdata; -} - -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; -} - -$("body").on("input change paste", "#notaryProfileSettings input,#notaryProfileSettings select", function () { - getStampSvgWithValues({ - name: $("#settingsModal #notary_name").val(), - location: $("#settingsModal #notary_location").val(), - expires: $("#settingsModal #notary_expires").val(), - idnumber: $("#settingsModal #notary_idnumber").val(), - state: $("#settingsModal #notary_state option:selected").val() - }, function (svg) { - $("#settingsModal #stamp-preview").attr("src", "data:image/svg+xml;base64," + btoa(svg)); - }); -}); - -$("body").on("input change paste", "#appOptionsSettings select", function () { - setAppTheme($("#appOptionsSettings #color_theme option:selected").val()); - setButtonSize($("#appOptionsSettings #button_size option:selected").val()); -}); function setAppTheme(theme) { if (typeof theme != "string") { @@ -230,38 +34,6 @@ function setButtonSize(size) { $(".btn").removeClass(["btn-sm", "btn-lg", "btn-"]).addClass("btn-" + size); } -function showToast(message) { - $("#toastBox .toast-body").html(message); - toastEl.show(); -} - -var toastEl = new bootstrap.Toast(document.getElementById("toastBox")); - -function showAlert(message) { - $("#alertModal .modal-body").html(message); - new bootstrap.Modal(document.getElementById('alertModal')).show(); -} - -var passwordModalCallback = function (pass) {}; - -function showPasswordPrompt(message, callback) { - $("#passwordModalText").html(message); - $("#passwordModalInput").val(""); - passwordModalCallback = callback; - new bootstrap.Modal(document.getElementById('passwordModal')).show(); -} - -$("#passwordModal").on("shown.bs.modal", function () { - $("#passwordModalInput").focus(); -}); - -$(".modal").on("keydown", function (e) { - if (e.keyCode == 13) { - // Prevent overlapping modals from all getting clicked - e.stopPropagation(); - $(this).find(".btn-default").first().click(); - } -}); $(document).ready(function () { setButtonSize(getStorage("button_size")); diff --git a/src/js/popups.js b/src/js/popups.js new file mode 100644 index 0000000..b144f49 --- /dev/null +++ b/src/js/popups.js @@ -0,0 +1,28 @@ +/* + * 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/. + */ + + +function showToast(message) { + $("#toastBox .toast-body").html(message); + toastEl.show(); +} + +var toastEl = new bootstrap.Toast(document.getElementById("toastBox")); + +function showAlert(message) { + $("#alertModal .modal-body").html(message); + new bootstrap.Modal(document.getElementById('alertModal')).show(); +} + +var passwordModalCallback = function (pass) {}; + +function showPasswordPrompt(message, callback) { + $("#passwordModalText").html(message); + $("#passwordModalInput").val(""); + passwordModalCallback = callback; + new bootstrap.Modal(document.getElementById('passwordModal')).show(); +} \ No newline at end of file diff --git a/src/js/settings.js b/src/js/settings.js new file mode 100644 index 0000000..98b6fd1 --- /dev/null +++ b/src/js/settings.js @@ -0,0 +1,64 @@ +/* + * 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/. + */ + + +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")); + + $("#settingsModal #color_theme").val(inStorage("color_theme") ? getStorage("color_theme") : "purple"); + $("#settingsModal #button_size").val(getStorage("button_size") ? getStorage("button_size") : "sm"); + // 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"))); + } + + setStorage("color_theme", $("#appOptionsSettings #color_theme option:selected").val()); + setAppTheme(getStorage("color_theme")); + setStorage("button_size", $("#appOptionsSettings #button_size option:selected").val()); + setButtonSize(getStorage("button_size")); + showToast(" Settings saved."); +} \ No newline at end of file diff --git a/src/js/signaturepad.js b/src/js/signaturepad.js new file mode 100644 index 0000000..0a7bb91 --- /dev/null +++ b/src/js/signaturepad.js @@ -0,0 +1,115 @@ +/* + * 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 signaturePad; + +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 signatureRemoteModalOpen() { + var url = getSignatureServerUrl(); + $("#signatureRemoteUrlLabel").text(url); + $("#signatureRemoteQRCode").html(""); + new QRCode(document.getElementById("signatureRemoteQRCode"), url); + new bootstrap.Modal(document.getElementById('signatureRemoteModal')).show(); +} + + +function handleRemoteSignatureData(data) { + if (!$("#signatureModal").hasClass("show")) { + return; + } + var canvas = document.getElementById("signaturecanvas"); + signaturePad.fromData(scaleSignatureData(data, canvas.width, canvas.height)); +} + +function scaleSignatureData(data, width, height) { + // Get width and height of data + // Get the minimum positions too for adding a bit of margin + var oldwidth = 0; + var oldheight = 0; + var oldminX = 999999999; + var oldminY = 999999999; + for (var i = 0; i < data.length; i++) { + for (var j = 0; j < data[i].points.length; j++) { + oldwidth = Math.max(data[i].points[j].x, oldwidth); + oldheight = Math.max(data[i].points[j].y, oldheight); + oldminX = Math.min(data[i].points[j].x, oldminX); + oldminY = Math.min(data[i].points[j].y, oldminY); + } + } + var xPad = oldminX / 2; + var yPad = oldminY / 2; + // Calculate scale ratios + var scaleX = (oldwidth + xPad * 2) / width; + var scaleY = (oldheight + yPad * 2) / height; + // Pick the largest scale ratio and use only that one so it maintains aspect ratio + var scale = Math.max(scaleX, scaleY); + // Loop over the old data and scale the points into a new signature data object + var newdata = []; + for (var i = 0; i < data.length; i++) { + var newpoints = []; + for (var j = 0; j < data[i].points.length; j++) { + newpoints.push({ + time: data[i].points[j].time, + x: (data[i].points[j].x + xPad) / scale, + y: (data[i].points[j].y + yPad) / scale + }); + } + newdata.push({ + color: data[i].color, + points: newpoints + }); + } + return newdata; +} \ No newline at end of file