@groupdocs.examples.jquery/signature
Version:
jQuery plugin that allows to display and sign documents supported by groupdocs libraries APIs
1,347 lines (1,268 loc) • 77.6 kB
JavaScript
/**
* groupdocs.signature Plugin
* Copyright (c) 2018 Aspose Pty Ltd
* Licensed under MIT.
* @author Aspose Pty Ltd
* @version 1.3.0
*/
/*
******************************************************************
******************************************************************
GLOBAL VARIABLES
******************************************************************
******************************************************************
*/
var signatureImageIndex = 0;
var signaturesList = [];
var currentDocumentGuid = "";
var signedDocumentGuid = "";
var signature = {
id: "",
signaturePassword: "",
signatureComment: "",
signatureType: "",
left: 0,
top: 0,
imageWidth: 0,
imageHeight: 0,
signatureGuid: "",
reason: "",
contact: "",
address: "",
date: "",
pageNumber: 0,
angle: 0
};
var draggableSignaturePosition = {};
var userMouseClick = ('ontouch' in document.documentElement) ? 'touch click' : 'click';
var contextMenuButtons = ["fas fa-arrows-alt fa-sm", "fas fa-unlock gd-lock-ratio", "fas fa-copy gd-copy-signature", "fas fa-trash-alt fa-sm gd-delete-signature"];
var mergedFonts = [];
var dataImagePrefix = 'data:image/png;base64,';
var triggerCopyResize = false;
var triggerCopyDrag = false;
$(document).ready(function () {
/*
******************************************************************
NAV BAR CONTROLS
******************************************************************
*/
//////////////////////////////////////////////////
// Get supported fonts
//////////////////////////////////////////////////
getFonts();
//////////////////////////////////////////////////
// Disable default download event
//////////////////////////////////////////////////
$('#gd-btn-download').off(userMouseClick);
$('.gd-modal-body').on('click', '.gd-filetree-name', function (e) {
$("#gd-signature-context-panel").hide();
signaturesList = [];
});
//////////////////////////////////////////////////
// Sign document
//////////////////////////////////////////////////
$("#gd-nav-save").on(userMouseClick, function () {
if (documentGuid && signaturesList.length > 0) {
sign();
} else {
printMessage("Please open document and add signature");
}
});
//////////////////////////////////////////////////
// Fix for tooltips of the dropdowns
//////////////////////////////////////////////////
$('#gd-download-val-container').on(userMouseClick, function (e) {
if ($(this).hasClass('open')) {
$('#gd-btn-download-value').parent().find('.gd-tooltip').css('display', 'none');
} else {
$('#gd-btn-download-value').parent().find('.gd-tooltip').css('display', 'initial');
}
});
//////////////////////////////////////////////////
// Open sign context panel
//////////////////////////////////////////////////
$('.gd-tool').on(userMouseClick, function (e) {
if (typeof documentGuid == "undefined" || documentGuid == "") {
printMessage("Please open document first");
} else {
closeAddCode();
closeAddUpload();
var button = $(this);
var type = button.attr("signature-type");
if (type) {
signature.signatureType = type;
}
var typeTitle = button.attr("signature-type-title");
var gd = $('#gd-signature-context-panel');
if (button[0].className.indexOf("gd-tool-inactive") > 0) {
loadSignaturesTree('');
if (isMobile()) {
$('.gd-tool-tooltip-mobile').hide();
}
$('#gd-signature-context-panel-title').html(typeTitle);
gd.show();
inactiveAll();
button.removeClass("gd-tool-inactive");
button.addClass("gd-tool-active");
} else {
if (isMobile()) {
$('.gd-tool-tooltip-mobile').show();
}
$('#gd-signature-context-panel-title').html("");
gd.hide();
button.removeClass("gd-tool-active");
button.addClass("gd-tool-inactive");
}
gd.toggleClass(type);
}
});
//////////////////////////////////////////////////
// Upload signature event
//////////////////////////////////////////////////
$('#gd-upload-input').on('change', function (e) {
var fileName = '';
$.each( $(this)[0].files, function(index, elem) {
fileName += elem.name + ', ';
});
$("#gd-upload-title").html(fileName.substring(0, fileName.lastIndexOf(',')));
$('#gd-add-upload-file').addClass('active');
});
$('#gd-add-upload-file').on(userMouseClick, function (e) {
e.preventDefault();
var uploadFiles = $("#gd-upload-input").get(0).files;
// upload file
if (uploadFiles.length > 0) {
if ("digital" == signature.signatureType) {
uploadSignature(uploadFiles[0], 0, "", loadSignaturesTree);
} else {
for (var i = 0; i < uploadFiles.length - 1; i++) {
// upload local file
uploadSignature(uploadFiles[i], i, "");
}
uploadSignature(uploadFiles[uploadFiles.length - 1], uploadFiles.length - 1, "", loadSignaturesTree);
}
closeAddUpload();
}
});
$('#gd-close-upload-signature').on(userMouseClick, function () {
resetUploadFiles();
closeAddUpload();
});
//////////////////////////////////////////////////
// Export drawn image signature
//////////////////////////////////////////////////
$('.gd-modal-lightbox').on(userMouseClick, '#bcPaint-export', function () {
var drawnImage = $.fn.bcPaint.export();
saveDrawnImage(drawnImage);
toggleLightBox(false);
});
//////////////////////////////////////////////////
// Download event
//////////////////////////////////////////////////
$('#gd-btn-download-value > li').bind(userMouseClick, function (e) {
download($(this));
});
//////////////////////////////////////////////////
// Upload button click event
//////////////////////////////////////////////////
$('#gd-btn-upload').on(userMouseClick, function (e) {
$(".gd-modal-dialog").removeClass("gd-signature-modal-dialog");
});
//////////////////////////////////////////////////
//Signature click event
//////////////////////////////////////////////////
$('#gd-panzoom').on(userMouseClick + 'touchstart mousedown', '.gd-signature', function (e) {
if (!$(e.target).hasClass("gd-font-size")) {
hideAllContextMenu();
var signature = $(e.target).closest('.gd-signature');
var contextMenu = signature.find('.gd-context-menu');
showContextMenuFor(signature);
if (signature.find('.gd-draw-text').length) {
var textarea = signature.find('textarea');
$.fn.textGenerator.init(signature.id, null, textarea.val(), contextMenu);
textarea.focus();
}
} else {
e.target.focus();
}
});
//////////////////////////////////////////////////
//Signature click event
//////////////////////////////////////////////////
$('#gd-panzoom').on(userMouseClick, '.gd-signature-image', function (e) {
if ($(this.parentElement).find(".gd-context-menu")[0].className.indexOf('hidden') > 0) {
hideAllContextMenu();
var elem = $(this.parentElement).find(".gd-context-menu");
elem.removeClass("hidden");
}
});
$('#gd-container').on(userMouseClick, function (e) {
var elem = $(e.target);
for (var i = 0; i < 5; i++) {
if (elem && elem[0].id == "gd-context-menu") {
return;
}
elem = elem.parent();
}
if(!$(e.target).hasClass("gd-signature-image") && !$(e.target).hasClass("gd-text") && $(e.target).attr("id") != "gd-new-signature"){
hideAllContextMenu();
}
});
//////////////////////////////////////////////////
// Lock ratio click event
//////////////////////////////////////////////////
$('#gd-panzoom').on(userMouseClick, '.gd-lock-ratio', function (e) {
e.preventDefault();
e.stopPropagation();
// start monkey patch for setOption (see https://bugs.jqueryui.com/ticket/4186)
var oldSetOption = $.ui.resizable.prototype._setOption;
$.ui.resizable.prototype._setOption = function(key, value) {
oldSetOption.apply(this, arguments);
if (key === "aspectRatio") {
this._aspectRatio = !!value;
}
};
// end monkey patch for setOption
var button = $(e.target);
var sigantureDragable = $(e.target).closest('.ui-draggable');
var isLocked = sigantureDragable.hasClass('ratio-locked');
if(isLocked){
sigantureDragable.removeClass('ratio-locked');
button.removeClass('fa-lock').addClass('fa-unlock');
sigantureDragable.find('.ui-resizable-handle').show();
sigantureDragable.resizable('option', 'aspectRatio', false);
}else{
sigantureDragable.addClass('ratio-locked');
button.removeClass('fa-unlock').addClass('fa-lock');
sigantureDragable.find('.ui-resizable-handle').hide();
sigantureDragable.find('.ui-resizable-se').show();
sigantureDragable.resizable('option', 'aspectRatio', true);
}
});
//////////////////////////////////////////////////
// Copy signature on all pages click event
//////////////////////////////////////////////////
$('#gd-panzoom').on(userMouseClick, '.gd-copy-signature', function (e) {
e.preventDefault();
e.stopPropagation();
var signatureId = parseInt($(e.target).data("id").replace(/[^\d.]/g, ''));
// get signature data to copy
var signatureToCopy = $.grep(signaturesList, function (obj) { return obj.id === signatureId; })[0];
var position = {'left': signatureToCopy.left, 'top': signatureToCopy.top};
var imgElement = $('#gd-image-signature-' + signatureId);
var image = "text" != signatureToCopy.signatureType && imgElement ?
imgElement.attr('src').replace(dataImagePrefix, '') : "";
$(".gd-page").each(function(index, page){
var pageNumber = index + 1;
if (signatureToCopy.pageNumber != pageNumber) {
copySignature(signatureToCopy, pageNumber);
if ("text" == signature.signatureType) {
insertText($.fn.textGenerator.getProperties(), pageNumber, position);
} else {
insertImage(image, pageNumber, position);
}
}
});
});
//////////////////////////////////////////////////
// Delete signature click event
//////////////////////////////////////////////////
$('#gd-panzoom').on(userMouseClick, '.gd-delete-signature', function (e) {
e.preventDefault();
e.stopPropagation();
if (!confirm("Do you want to delete?")) {
return false;
}
var signatureId = parseInt($(e.target).data("id").replace(/[^\d.]/g, ''));
// get signature data to delete
var signatureToRemove = $.grep(signaturesList, function (obj) { return obj.id === signatureId; })[0];
if (signatureToRemove.signatureType == 'text' && isMobile()) {
var menuId = e.target.parentElement.parentElement.attributes['data-textMenuId'].value;
$('#' + menuId).remove();
}
e.target.parentElement.parentElement.remove();
// delete signature from the signatures list
signaturesList.splice($.inArray(signatureToRemove, signaturesList), 1);
});
//////////////////////////////////////////////////
// Header menu for mobile events
//////////////////////////////////////////////////
$('#gd-mobile-menu-open').on(userMouseClick, function (e) {
$('#gd-left-bar-wrapper').show();
$('.gd-tool-tooltip-mobile').show();
$('#gd-mobile-menu-close').show();
$('#gd-mobile-menu-open').hide();
});
$('#gd-mobile-menu-close').on(userMouseClick, function (e) {
hideMobileMenu();
});
//////////////////////////////////////////////////
// Close lightbox dialog event
//////////////////////////////////////////////////
$('.gd-lightbox-close').on(userMouseClick, function () {
toggleLightBox(false)
});
//////////////////////////////////////////////////
// Choose signature event by click
//////////////////////////////////////////////////
$('#gd-signature-list').on(userMouseClick, '.gd-signature-item', function (e) {
var sign = $(this);
selectSignature(sign);
});
//////////////////////////////////////////////////
// Create new signature
//////////////////////////////////////////////////
$('#gd-new-signature').on(userMouseClick, function (e) {
switch (signature.signatureType) {
case "hand":
toggleLightBox(true, "Draw signature", "", getDrawSignContent());
$("#gd-draw-image").bcPaint();
fillLightBoxHeader(getDrawSignHeader());
break;
case "stamp":
var html = $.fn.stampGenerator.addInitialShape();
toggleLightBox(true, "Draw signature", html.header);
$.fn.stampGenerator.addShape(0);
break;
case "barCode":
case "qrCode":
$("#gd-signature-context-panel").opticalCodeGenerator();
changeListClass("gd-signature-list-wrapper-add");
break;
case "text":
if (isMobile()) {
hideMobileMenu();
} else {
$('#gd-signature-context-panel').hide();
inactiveAll();
}
initSignature(getCurrentPageNumber());
insertText();
break;
case "image":
openUploadSignatures("Add image signature", true);
break;
case "digital":
openUploadSignatures("Add digital signature", false);
break;
}
});
});
/*
******************************************************************
FUNCTIONS
******************************************************************
*/
function copySignature(signatureToCopy, pageNumber) {
signature = {};
signature.pageNumber = pageNumber;
signature.top = signatureToCopy.top;
signature.left = signatureToCopy.left;
signature.imageHeight = signatureToCopy.imageHeight;
signature.imageWidth = signatureToCopy.imageWidth;
signature.angle = signatureToCopy.angle;
signature.signatureGuid = signatureToCopy.signatureGuid;
signature.signatureType = signatureToCopy.signatureType;
signature.contact = signatureToCopy.contact;
signature.reason = signatureToCopy.reason;
signature.address = signatureToCopy.address;
signature.date = signatureToCopy.date;
signature.signatureComment = signatureToCopy.signatureComment;
signature.signaturePassword = signatureToCopy.signaturePassword;
}
/**
* Close add code panel
*/
function closeAddCode() {
$("#gd-add-optical-signature").remove();
changeListClass();
}
function closeAddUpload() {
$("#gd-upload-signature").hide();
changeListClass();
}
/**
* For correct scroll, while new code panel added/removed
*
* @param addClass
*/
function changeListClass(addClass) {
if (addClass) {
if (addClass == "gd-signature-list-wrapper-add-img") {
$("#gd-signature-list-wrapper").removeClass("gd-signature-list-wrapper-add");
}
$("#gd-signature-list-wrapper").addClass(addClass);
} else {
$("#gd-signature-list-wrapper").removeClass("gd-signature-list-wrapper-add-img");
$("#gd-signature-list-wrapper").removeClass("gd-signature-list-wrapper-add");
}
}
/**
* Hide all menu. For mobile only.
*/
function hideMobileMenu() {
$('#gd-left-bar-wrapper').hide();
$('#gd-mobile-menu-open').show();
$('#gd-mobile-menu-close').hide();
$('#gd-signature-context-panel').hide();
inactiveAll();
}
/**
* Open window for upload signatures
*/
function openUploadSignatures(title, multiple) {
resetUploadFiles();
$("#gd-upload-panel-title").html(title);
$("#gd-upload-input")[0].multiple = multiple;
$("#gd-upload-signature").show();
changeListClass("gd-signature-list-wrapper-add-img");
}
function resetUploadFiles() {
$("#gd-upload-title").html("Upload file");
$("#gd-upload-input").val('');
$('#gd-add-upload-file').removeClass('active');
}
function fillLightBoxHeader(header) {
$("#gd-lightbox-header").append(header);
}
/**
* Get html for lightbox header to create new image
* @returns {string}
*/
function getDrawSignHeader() {
return $.fn.bcPaint.getHeader();
}
/**
* Get html for lightbox content to create new image
* @returns {string}
*/
function getDrawSignContent() {
return '<div id="gd-draw-image">' +
// draw area will be here
'</div>';
}
/**
* Fade left bar menu
* @param on
*/
function fadeLeftBar(on) {
if (on) {
$('#gd-left-bar-fade').show();
$('#gd-left-bar-spinner').show();
} else {
$('#gd-left-bar-fade').hide();
$('#gd-left-bar-spinner').hide();
}
}
/**
* Select signature from list
* @param sign
*/
function selectSignature(sign, pageNumber) {
if ("digital" == signature.signatureType) {
openDigitalPanel(sign);
return;
}
signature.signatureGuid = sign.attr("data-guid");
loadSignatureImage(pageNumber);
$('#gd-signature-context-panel').hide();
if (isMobile()) {
$('#gd-left-bar-wrapper').hide();
$('#gd-mobile-menu-open').show();
$('#gd-mobile-menu-close').hide();
}
inactiveAll();
}
/**
* Inactive all menu items in left bar
*/
function inactiveAll() {
$.each($('.gd-tool'), function (index, elem) {
var attribute = elem.attributes['signature-type'];
$('#gd-signature-context-panel').removeClass(attribute.value);
});
$('.gd-tool-active').addClass("gd-tool-inactive");
$('.gd-tool-active').removeClass("gd-tool-active");
}
/**
* Delete saved signature
* @param guid
*/
function deleteSignatureFile(guid) {
var data = { guid: guid, signatureType: signature.signatureType };
// show loading spinner
fadeLeftBar(true);
$.ajax({
type: 'POST',
url: getApplicationPath('deleteSignatureFile'),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
// hide loading spinner
fadeLeftBar(false);
// open error popup
if (returnedData && returnedData.message != undefined) {
toggleModalDialog(false, "");
printMessage(returnedData.message);
return;
}
loadSignaturesTree('');
},
error: function (xhr, status, error) {
// hide loading spinner
fadeLeftBar(false);
var err = eval("(" + xhr.responseText + ")");
console.log(err.message);
// open error popup
toggleModalDialog(false, "");
printMessage(err.message);
}
});
}
/**
* Return html for empty list view
*
* @returns {string}
*/
function getHtmlEmptyList() {
var signTypeClass;
switch (signature.signatureType) {
case "image":
signTypeClass = 'fa-image';
break;
case "text":
signTypeClass = 'fa-font';
break;
case "digital":
signTypeClass = 'fa-fingerprint';
break;
case "hand":
signTypeClass = 'fa-signature';
break;
case "stamp":
signTypeClass = 'fa-stamp';
break;
case "qrCode":
signTypeClass = 'fa-qrcode';
break;
case "barCode":
signTypeClass = 'fa-barcode';
break;
}
return '<i class="fas ' + signTypeClass + ' fa-lg"></i>' +
'<span class="gd-empty-list-text">There is no ' + signature.signatureType + ' signatures yet.</span>';
}
/**
* Load file tree
* @param {string} dir - files location directory
* @param {object} callback - function that will be executed after ajax call
*/
function loadSignaturesTree(dir, callback) {
dir = dir||'';
$('#gd-signature-list').html("");
$('#gd-signature-empty-list').html("");
var data = { path: dir, signatureType: signature.signatureType };
currentDirectory = dir;
// show loading spinner
fadeLeftBar(true);
// get data
$.ajax({
type: 'POST',
url: getApplicationPath('loadFileTree'),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
// hide loading spinner
fadeLeftBar(false);
// open error popup
if (returnedData && returnedData.message != undefined) {
toggleModalDialog(false, "");
printMessage(returnedData.message);
return;
}
if (returnedData && returnedData.length == 0) {
$('#gd-signature-empty-list').append(getHtmlEmptyList());
return;
}
// append files to tree list
$.each(returnedData, function (index, elem) {
// document name
var name = elem.name;
if (signature.signatureType == 'qrCode' || signature.signatureType == 'barCode' || signature.signatureType == 'text') {
name = elem.text;
}
// document guid
var guid = elem.guid;
// append signature
if (elem.isDirectory) {
$('#gd-signature-list').append('<div class="gd-signature">' +
'<i class="fa fa-folder"></i>' +
'<div class="gd-signature-name" data-guid="' + guid + '">' + name + '</div>' +
'</div>');
} else {
var imageBlock = name;
var textSignatureClass = "";
var textStyle = "";
switch(signature.signatureType){
case "digital":
imageBlock = '<div class="gd-signature-thumbnail-digital"><i class="fas fa-fingerprint fa-lg fa-inverse"></i></div>';
break;
case "text":
imageBlock = "";
textSignatureClass = "text";
textStyle = 'style="color: ' + elem.fontColor + ';"';
break;
default:
imageBlock = '<image class="gd-signature-thumbnail-' + signature.signatureType + '" src="data:image/png;base64,' + elem.image + '" alt></image>';
}
$('#gd-signature-list').append(
'<div class="gd-signature-item-wrapper gd-signature-thumbnail">'+
'<div data-guid="' + guid + '" id="gd-signature-item-' + index + '" class="gd-signature-item ui-draggable ui-draggable-handle">' +
imageBlock +
'<div data-guid="' + guid + '" class="gd-signature-title ' + textSignatureClass + '">' +
'<label for="gd-signature-' + index + '" class="gd-signature-name" ' + textStyle + '>' + name + '</label>' +
'</div>' +
'<i class="fa fa-trash-o"></i>' +
'</div>'+
'</div>');
if (!isMobile() && "digital" != signature.signatureType) {
$('#gd-signature-item-' + index).draggable({
containment: "#gd-panzoom",
start: function () {
$('#gd-signature-list').removeClass("gd-signature-list-scroll");
},
stop: function (event, image) {
var sign = $(this);
var position = getMousePosition(event);
var currentPage = document.elementFromPoint(position.x, position.y);
if(currentPage && $(currentPage).parent().parent() && $(currentPage).parent().parent().hasClass("gd-page")) {
var documentPage = $(currentPage).parent().parent()[0];
draggableSignaturePosition.left = position.x - $(documentPage).offset().left - ($(sign)[0].clientWidth / 2);
draggableSignaturePosition.top = position.y - $(documentPage).offset().top - ($(sign)[0].clientHeight / 2);
var id = $(currentPage).parent().parent().attr("id").replace(/[^\d.]/g, '');
var pageNumber = parseInt(id);
selectSignature(sign, pageNumber);
} else {
$(this)[0].style = 'position: relative';
}
$('#gd-signature-list').addClass("gd-signature-list-scroll");
}
});
}
$('#gd-signature-item-' + index).on(userMouseClick, '.fa-trash-o', function (e) {
e.preventDefault();
e.stopPropagation();
var signatureGuid = $(this).parent().attr("data-guid");
var signatureToRemove = $.grep(signaturesList, function (obj) { return obj.signatureGuid == signatureGuid; })[0];
if (signatureToRemove) {
printMessage("This signature has already been added to the document page(s). Please remove it from the page(s) first.");
return;
}
if (!confirm("Do you want to delete?")) {
return false;
}
deleteSignatureFile(signatureGuid);
});
}
});
// check if document was changed
if (currentDocumentGuid != documentGuid) {
// if changed - drop signatures from previous signing
signaturesList = [];
signatureImageIndex = 0;
currentDocumentGuid = documentGuid;
}
},
error: function (xhr, status, error) {
// hide loading spinner
fadeLeftBar(false);
var err = eval("(" + xhr.responseText + ")");
console.log(err.message);
// open error popup
toggleModalDialog(false, "");
printMessage(err.message);
}
}).done(function (data) {
if (typeof callback == "function") {
callback(data);
}
});
}
function getMousePosition(event) {
var mouse = {
x: 0,
y: 0
};
var ev = event || window.event; //Moz || IE
if (ev.pageX || ev.touches[0].pageX) { //Moz
mouse.x = (typeof ev.pageX != "undefined" && ev.pageX != 0) ? ev.pageX : ev.touches[0].pageX;
mouse.y = (typeof ev.pageY != "undefined" && ev.pageY != 0) ? ev.pageY : ev.touches[0].pageY;
} else if (ev.clientX) { //IE
mouse.x = ev.clientX + document.body.scrollLeft;
mouse.y = ev.clientY + document.body.scrollTop;
}
return mouse;
}
/**
* Upload signature
* @param {file} file - File for uploading
* @param {int} index - Number of the file to upload
* @param {string} url - URL of the file, set it if URL used instead of file
*/
function uploadSignature(file, index, url, callback) {
// prepare form data for uploading
var formData = new FormData();
// add local file for uploading
formData.append("file", file);
if (typeof url == "undefined") {
url = "";
}
// add URL if set
formData.append("url", url);
formData.append("signatureType", signature.signatureType);
formData.append("rewrite", rewrite);
$.ajax({
type: 'POST',
url: getApplicationPath('uploadDocument'),
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (returnedData) {
if (returnedData.message != undefined) {
toggleModalDialog(false, "");
// open error popup
printMessage(returnedData.message);
return;
}
},
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
toggleModalDialog(false, "");
// open error popup
printMessage(err.message);
}
}).done(function () {
if (typeof callback == "function") {
callback();
}
});
}
/**
* Sign current document
*/
function sign(download) {
$('#gd-modal-spinner').show();
currentDocumentGuid = documentGuid;
var documentType = getDocumentFormat(documentGuid).format;
var data = {
guid: documentGuid,
password: password,
signaturesData: signaturesList,
documentType: documentType
};
if (download) {
fadeAll(true);
var request = new XMLHttpRequest();
request.open('POST', getApplicationPath('downloadSigned'), true);
request.setRequestHeader('Content-Type', 'application/json');
request.responseType = 'blob';
request.onload = function() {
fadeAll(false);
// Only handle status code 200
if(request.status === 200) {
// Try to find out the filename from the content disposition `filename` value
var filename = documentGuid.replace(/\\/g,"/").split('/').pop();
// The actual download
var blob = new Blob([request.response], { type: 'application/' + documentGuid.split('.').pop().toLowerCase() });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = filename;
// for ff we should append element and then remove it
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
};
request.send(JSON.stringify(data));
} else {
var spinner = $('<div id="gd-modal-spinner" style="display:block;"><i class="fa fa-circle-o-notch fa-spin"></i> Loading... Please wait.</div>').show();
toggleSuccessModalDialog(true, 'Signing document', spinner);
// sign the document
$.ajax({
type: 'POST',
url: getApplicationPath('sign'),
data: JSON.stringify(data),
contentType: 'application/json',
dataType: 'json',
success: function (returnedData, status, request) {
$('#gd-modal-spinner').hide();
if (returnedData && returnedData.message != undefined) {
// open error popup
printMessage(returnedData.message);
return;
}
signedDocumentGuid = returnedData.guid;
// prepare signing results HTML
var result = '<div id="gd-modal-signed"><div class="check_mark">\n' +
' <div class="sa-icon sa-success animate">\n' +
' <span class="sa-line sa-tip animateSuccessTip"></span>\n' +
' <span class="sa-line sa-long animateSuccessLong"></span>\n' +
' <div class="sa-placeholder"></div>\n' +
' <div class="sa-fix"></div>\n' +
' </div>\n' +
'</div></div>';
// show signing results
toggleSuccessModalDialog(true, 'Document signed', result);
$('.gd-modal-close-action').on('click', function () {
toggleSuccessModalDialog(false, 'Document signed', result)
$('.gd-modal-close-action').off('click').click(closeModal);
});
},
error: function (xhr, status, error) {
$('#gd-modal-spinner').hide();
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
// open error popup
printMessage(err.message);
}
});
}
}
function toggleSuccessModalDialog(open, title, content) {
if (open) {
$('#modalDialog .gd-modal-title').text(title);
$('#modalDialog')
.addClass('success')
.css('opacity', 0)
.fadeIn('fast')
.animate(
{ opacity: 1 },
{ queue: false, duration: 'fast' }
);
$('#modalDialog').addClass('in');
$(".gd-modal-body").append(content);
} else {
$('#modalDialog').removeClass('in');
$('#modalDialog').removeClass('success');
$('#modalDialog')
.css('opacity', 1)
.fadeIn('fast')
.animate(
{ opacity: 0 },
{ queue: false, duration: 'fast' }
)
.css('display', 'none');
$(".gd-modal-body").html('');
}
}
/**
* Add digitally signed marker
* @param {string} contact - digital signature comment
*/
function addDigitalMarker(contact){
var marker = '<div class="gd-digital-marker">'+
'<i class="fas fa-info-circle"></i>'+
'<div>Digitaly signed : ' + contact + '</div>'+
'</div>';
$(".gd-page").each(function(index, page){
$(page).append(marker);
})
}
/**
* Save drawn image signature
* @param {string} image - Base64 encoded image
*/
function saveDrawnImage(image) {
fadeAll(true);
hideAllContextMenu();
// current document guid is taken from the viewer.js globals
var data = { image: image };
// sign the document
$.ajax({
type: 'POST',
url: getApplicationPath("saveImage"),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
fadeAll(false);
if (returnedData.message != undefined) {
// open error popup
printMessage(returnedData.message);
return;
}
// load signatures from storage
loadSignaturesTree('');
},
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
fadeAll(false);
// open error popup
printMessage(err.message);
}
});
}
/**
* Save drawn stamp signature
*/
function saveDrawnStamp(callback) {
fadeAll(true);
hideAllContextMenu();
//get drawn stamp data
stampData = $.fn.stampGenerator.getStampData();
// initiate image
var image = "";
// draw empty canvas - required to resize and crop stamp for its real size
var cropedCanvas = "<canvas id='gd-croped-stamp' width='" + stampData[stampData.length - 1].width + "' height='" + stampData[stampData.length - 1].height + "'></canvas>";
// combine all stamp lines to one image
$("#gd-lightbox-body").append(cropedCanvas);
var ctxCroped = $("#gd-croped-stamp")[0].getContext("2d");
// get drawn stamp padding from canvas border
var biggestWidth = stampData[stampData.length - 1].width;
// combine stamp lines
stampData.reverse()
$(".csg-preview").each(function (index, shape) {
// calculate stamp real size and paddings
var offset = biggestWidth - stampData[index].width;
// crop canvas empty pixels
if (offset != 0) {
offset = offset / 2;
}
ctxCroped.drawImage(shape, offset, offset);
// remove old canvases
$(shape).remove();
});
// get image from canvas
image = $("#gd-croped-stamp")[0].toDataURL("image/png");
// prepare data for ajax
stampData.reverse();
var data = { image: image, stampData: stampData };
// save the stamp image and xml description in the storage
$.ajax({
type: 'POST',
url: getApplicationPath("saveStamp"),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
fadeAll(false);
if (returnedData.message != undefined) {
// open error popup
printMessage(returnedData.message);
return;
}
// set signature data
signature.signatureGuid = returnedData.guid;
signature.imageHeight = stampData[0].height;
signature.imageWidth = stampData[0].width;
loadSignaturesTree('');
$(".gd-signature-select").removeClass("gd-signing-disabled");
toggleLightBox(false, "", "");
},
error: function (xhr, status, error) {
fadeAll(false);
toggleLightBox(false, "", "");
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
// open error popup
printMessage(err ? err.message : "Error");
}
}).done(function (data) {
if (typeof callback == "function") {
callback(data);
}
});
}
/**
* Save drawn Text signature
* @param {Object} properties - Text properties
*/
function saveDrawnText(properties, callback) {
if (!properties.text) {
return;
}
var newId = null;
if (properties && !properties.imageGuid) {
newId = properties.id;
}
var data = { properties: properties };
// sign the document
$.ajax({
type: 'POST',
url: getApplicationPath("saveText"),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
if (returnedData.message != undefined) {
// open error popup
printMessage(returnedData.message);
return;
}
if (newId) {
var newSignature = $.grep(signaturesList, function (obj) { return newId == obj.id; })[0];
if (newSignature) {
// set current signature data
newSignature.signatureGuid = returnedData.imageGuid;
newSignature.imageHeight = returnedData.height;
newSignature.imageWidth = returnedData.width;
}
}
$.each(signaturesList, function (index, sign) {
if (sign.signatureGuid == returnedData.imageGuid) {
var textField = $("#gd-draggable-helper-" + sign.id).find('#gd-text');
initCssForTextField(textField, properties);
}
});
if ($('#gd-signature-context-panel')[0].style.display != 'none' &&
$('#gd-text-sign')[0].className.indexOf('gd-tool-active') > 0) {
signature.signatureType = 'text';
loadSignaturesTree('');
}
},
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
console.log(err ? err.message : error);
// open error popup
printMessage(err ? err.message : error);
}
}).done(function (data) {
if (typeof callback == "function" && data) {
callback(data);
}
});
}
function initCssForTextField(textField, properties) {
textField.val(properties.text);
textField.css("text-decoration", properties.underline ? "underline" : "unset");
textField.css("font-style", properties.italic ? "italic" : "unset");
textField.css("font-weight", properties.bold ? "bold" : "unset");
textField.css("color", properties.fontColor);
textField.css("font-family", properties.font);
textField.css("font-size", properties.fontSize ? properties.fontSize + 'px' : '');
textField.parent().parent().find(".gd-font-size").val(properties.fontSize);
}
/**
* Get HTML content for signature information modal
**/
function openDigitalPanel(currentCertificate) {
var documentFormat = getDocumentFormat(documentGuid, false);
var inputs = "";
if ($(".gd-digital-inputs").length == 0) {
var addActive = 'active';
var signatureAdded = $.grep(signaturesList, function (obj) { return obj.signatureGuid == signature.signatureGuid; });
if (signatureAdded && signatureAdded.length > 0 && signatureAdded[0]) {
addActive= '';
}
// generate signature information imputs for depending from current document type
if (documentFormat.format.indexOf("Portable Document") >= 0) {
inputs = '<div class="gd-digital-inputs">' +
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-comment"></i>' +
'<input id="gd-reason" type="text" placeholder="Reason" > ' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-envelope"></i>' +
'<input id="gd-contact" type="text" placeholder="Contact">' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-map-marker-alt"></i>' +
'<input id="gd-location" type="text" placeholder="Location">' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-key"></i>' +
'<input id="gd-signature-password" type="password" placeholder="Password">' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fa fa-calendar" aria-hidden="true"></i>' +
'<input type="text" id="gd-datepicker" placeholder="Date">' +
'</div>'+
'<div id="gd-sign-digital" class="gd-sign-digital ' + addActive + '">Sign</div>' +
'</div>';
} else if (documentFormat.format.indexOf("Word") >= 0 || documentFormat.format.indexOf("Excel") >= 0) {
inputs = '<div class="gd-digital-inputs">' +
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-comment"></i>' +
'<input id="gd-signature-comment" type="text" placeholder="Comment" > ' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fas fa-key"></i>' +
'<input id="gd-signature-password" type="password" placeholder="Password">' +
'</div>'+
'<div class="gd-digital-input-wrapper">'+
'<i class="fa fa-calendar" aria-hidden="true"></i>' +
'<input type="text" id="gd-datepicker" placeholder="Date">' +
'</div>'+
'<div id="gd-sign-digital" class="gd-sign-digital ' + addActive + '">Sign</div>' +
'</div>';
} else {
return;
}
$(currentCertificate).parent().append(inputs);
$("#gd-datepicker").datepicker({ dateFormat: 'dd-mm-yy' });
$("#gd-sign-digital").on(userMouseClick, function (e) {
if ($(this).hasClass('active')) {
setAdditionalInformation(e);
if (!isMobile()) {
$('#gd-signature-context-panel').hide();
} else {
hideMobileMenu();
}
signaturesList.push(signature);
var digitalMarker = (signature.contact) ? signature.contact : signature.signatureComment;
addDigitalMarker(digitalMarker);
$('#gd-sign-digital').removeClass('active');
}
});
} else {
$(".gd-digital-inputs").remove();
}
}
/**
* Set signature additional information data
*/
function setAdditionalInformation(certificate) {
// save entered signature data on add additional information step
signature.reason = $("#gd-reason").val();
signature.contact = $("#gd-contact").val();
signature.address = $("#gd-location").val();
signature.date = $("#gd-datepicker").val();
signature.signaturePassword = $("#gd-signature-password").val();
signature.signatureComment = $("#gd-signature-comment").val();
signature.signatureGuid = $(certificate.target.parentElement.parentElement).find(".gd-signature-item").data("guid");
}
/**
* Get current page number
* @returns {number}
*/
function getCurrentPageNumber() {
var pagesAttr = $('#gd-page-num').text().split('/');
var currentPageNumber = parseInt(pagesAttr[0]);
return currentPageNumber;
}
/**
* Init signature properties
*
* @param currentPageNumber
*/
function initSignature(currentPageNumber) {
signature.pageNumber = currentPageNumber;
}
/**
* Get selected signature image stream
*/
function loadSignatureImage(pageNumber) {
if (!pageNumber) {
pageNumber = getCurrentPageNumber();
}
// current document guid is taken from the viewer.js globals
var data = { signatureType: signature.signatureType, guid: signature.signatureGuid, page: pageNumber, password: "" };
fadeAll(true);
hideAllContextMenu();
// load signature image from the storage
$.ajax({
type: 'POST',
url: getApplicationPath('loadSignatureImage'),
data: JSON.stringify(data),
contentType: 'application/json',
success: function (returnedData) {
fadeAll(false);
if (returnedData.message != undefined) {
toggleModalDialog(false, "");
// open error popup
printMessage(returnedData.message);
return;
}
// when ajax is done insert loaded image into the document page
toggleModalDialog(false, "");
// insert image over the selected document page
initSignature(pageNumber);
if ("text" == signature.signatureType) {
insertText(returnedData.props, pageNumber);
} else {
insertImage(returnedData.data, pageNumber);
}
},
error: function (xhr, status, error) {
fadeAll(false);
var err = eval("(" + xhr.responseText + ")");
console.log(err.Message);
toggleModalDialog(false, "");
// open error popup
printMessage(err.message);
}
});
}
function insertText(properties, pageNumber, position) {
if (!pageNumber) {
pageNumber = getCurrentPageNumber();
}
hideAllContextMenu();
// get HTML markup of the resize handles
var resizeHandles = getHtmlResizeHandles();
signature.id = signatureImageIndex;
signaturesList.push(signature);
// set document format
var style = "";
var addPositionClass;
if (draggableSignaturePosition && draggableSignaturePosition.left && draggableSignaturePosition.top) {
style += 'left: ' + draggableSignaturePosition.left + 'px; top: ' + draggableSignaturePosition.top + 'px;';
if (draggableSignaturePosition.top < 10) {
addPositionClass = "gd-context-menu-bottom";
} else {
addPositionClass = "gd-context-menu-top";
}
draggableSignaturePosition = {};
} else if (position) {
style += 'left: ' + position.left + 'px; top: ' + position.top + 'px;';
} else {
addPositionClass = "gd-context-menu-bottom";
}
var contextMenu = getContextMenu("gd-text-signature-" + signatureImageIndex, addPositionClass);
if (signature.imageWidth) {
style += "width: " + signature.imageWidth + "px;";
} else if (properties && properties.width) {
style += "width: " + properties.width + "px;";
} else {
style += isMobile() ? "width: 200px;" : "width: 100px;";
}
if (signature.imageHeight) {
style += "height: " + signature.imageHeight + "px";
} else if (properties && properties.height) {
style += "height: " + properties.height + "px";
} else {
style += isMobile() ? "height: 100px;" : "height: 50px;";
}
var imageGuid = properties ? properties.imageGuid : "";
// prepare signature image HTML
var signatureHtml = '<div id="gd-draggable-helper-' + signatureImageIndex + '" class="gd-draggable-helper gd-signature" style="' + style + '" data-textMenuId="menu-gd-text-signature-' + signatureImageIndex + '">' +
contextMenu +
'<div id="gd-draw-text-' + signatureImageIndex + '" data-image-guid="' + imageGuid + '" class="gd-draw-text"/>' +
resizeHandles +
'';
$("#gd-image-signature-" + signatureImageIndex).css('background-color', 'transparent');
// add signature to the selected page
$(signatureHtml).insertBefore($("#gd-page-" + pageNumber).find(".gd-wrapper")).delay(1000);
setDraggableAndResizable(pageNumber);
signature = {};
$.fn.textGenerator.create("gd-draggable-helper-" + signatureImageIndex, "menu-gd-text-signature-" + signatureImageIndex);
if (properties) {
$.fn.textGenerator.init("gd-draggable-helper-" + signatureImageIndex, properties);
// add new signature object into the list of signatures
} else {
signature.signatureType = 'text';
}
// increase signature index
signatureImageIndex = signatureImageIndex + 1;
}
function fixContextMenuTop(elem, top) {
if (top < 10) {
elem.addClass("gd-context-menu-bottom");
elem.removeClass("gd-context-menu-top");
} else {
elem.addClass("gd-context-menu-top");
elem.removeClass("gd-context-menu-bottom");
}
}
function setDraggableAndResizable(pageNumber) {
va