Edit in JSFiddle

// ------------------------------------------------------------------------------------------
// LacunaWebPKI: complete example (with jQuery and extra UI components)

var signatureProcessId = null;

var pki = new LacunaWebPKI({
    "format": 1,
    "allowedDomains": [
        "jsfiddle.net",
        "webpki.lacunasoftware.com"
    ],
    "expiration": null,
    "signature": "ClKvO1J22vAD+YmfANiKQLbcLE1lNraPKCel6tRM+ZxR+h6M/crtJYRRVGGz7hrdbM0Y0mfTu15RMYGqQMi1QNZS6GrT4vNzIayv552Fl0EFWQA7jWlctUwfYoHRHVEnCNx9YGXDiA9+yDoGlVwgTR7fjzNeS3Fen1MVIyKBF464gN0JvdiCRJMI47JGVDkPmKjcrYIvJs6y5Lg25RW4ZnBKVruS+HR2s3k8ZrV4y4RCQE4UYMKbukF9vsF+JqAEifRlPq2xLcrNdxBveVDSXS/LRHAcrZrMM+Iw4A79jl0ngWPcy+CwinAhT+3dxVo5ZWMRQFpmTkylEMDvTjV9wQ=="
});

function start() {
    log('Checking component installation ...');
    blockUI.start('Initializing Web PKI ...');
    pki.init({
        ready: onWebPkiReady,
        notInstalled: onWebPkiNotInstalled,
        defaultError: onWebPkiError
    });
}

function onWebPkiError(message, error, origin) {
    blockUI.stop();
    log('Web PKI error originated at ' + origin + ': ' + error);
    showModal('Error', 'Web PKI error: ' + message);
}

function onWebPkiNotInstalled (status, message) {
    log('Installation NOT ok: ' + message);
    blockUI.stop();
    showModal('Message', message + '<br/><br/>Click OK to go to installation page', function() {
        pki.redirectToInstallPage();
    });
}

function onWebPkiReady () {
    log('Component ready.');
    blockUI.message('Loading certificates ...');
    loadCertificates();
}

function refresh() {
    blockUI.start('Loading certificates ...');
    loadCertificates();
}

function loadCertificates() {
    log('Listing certificates ...');
    pki.listCertificates().success(function (certificates) {
        log('Certificates listed.');
        var select = $('#certificateSelect');
        $.each(certificates, function() {
            select.append(
                $('<option />')
                .val(this.thumbprint)
                .text(this.subjectName + ' (issued by ' + this.issuerName + ')')
            );
        });
        $('#signatureControlsPanel').show();
        blockUI.stop();
    });
}

// This function is called when the user clicks the button "Sign Dummy File"
function signFile() {
    blockUI.start('Signing ... (step 1/4)');
    // The first thing we'll do is read the certificate encoding
    var selectedCertThumb = $('#certificateSelect').val();
    log('Reading certificate binary encoding ...');
    pki.readCertificate(selectedCertThumb).success(onReadCertificateCompleted);
}

// This function is the callback for when the readCertificate operation is completed
function onReadCertificateCompleted(certEncoding) {
    log('Certificate binary encoding read, sending to server ...');
    blockUI.message('Signing ... (step 2/4)');
    // Now that we have acquired the certificate's encoding, we'll send that to the
    // server using Ajax
    $.ajax({
        url: 'https://webpki.lacunasoftware.com/api/Signature/Start',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            certificate: certEncoding
        }),
        dataType: 'json',
        success: onSignatureStartCompleted
    });
}

// This function is the callback for when the server replies back with the "to-sign-bytes"
// and digest algorithm oid.
function onSignatureStartCompleted(response) {
    log('Received response from server with bytes to sign and digest algorithm');
    log('toSign: ' + response.toSign);
    log('digestAlgorithmOid: ' + response.digestAlgorithmOid);
    log('Signing ...');
    blockUI.message('Signing ... (step 3/4)');
    signatureProcessId = response.processId;
    pki.signData({
        thumbprint: $('#certificateSelect').val(),
        data: response.toSign,
        digestAlgorithm: response.digestAlgorithmOid
    }).success(onSignDataCompleted);
}

// This function is the callback for when the signData operation is completed
function onSignDataCompleted(signature) {
    log('Signature completed, submitting to server ...');
    blockUI.message('Signing ... (step 4/4)');
    // We send the signature result back to the server, which will then use
    // its server-side SDK to assemble the signed PDF file
    $.ajax({
        url: 'https://webpki.lacunasoftware.com/api/Signature/Complete',
        method: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            processId: signatureProcessId,
            signature: signature
        }),
        success: onSignatureCompleteCompleted
    });
}

// This function is the callback for when the server replies back signalling that
// the signature process is completed and we may download the signed PDF file.
function onSignatureCompleteCompleted() {
    blockUI.stop();
    log('Process completed!');
    showModal('Message', 'Dummy file signed successfully. Click OK to download the signed file.', function (modalInstance) {
        document.location.href = 'https://webpki.lacunasoftware.com/api/Signature/' + signatureProcessId;
        modalInstance.dialog('close');
    });
}

function log(message) {
    if (window.console) {
        window.console.log(message);
    }
}

function showModal(title, message, okCallback) {
    $('#dialog').attr('title', title);
    $('#dialogMessage').html(message);
    $('#dialog').dialog({
        modal: true,
        width: 400,
        buttons: {
            'OK': function() {
                if (okCallback) {
                    okCallback($(this));
                } else {
                    $(this).dialog('close');
                }
            }
        }
    });
}

var blockUI = new function() {
    
    var start = function (msg) {
        if (msg) {
            message(msg);
        } else {
            message('Loading ...');
        }
        $.blockUI({ message: $('#blockPanel') });
    };
    
    var message = function (msg) {
        $('#blockPanel').html(msg);
    };
    
    var stop = function() {
        $.unblockUI();
    };
    
    this.start = start;
    this.message = message;
    this.stop = stop;
};

$(function() {
    $('#refreshButton').click(refresh);
    $('#signFileButton').click(signFile);
    start();
});
<div id="signatureControlsPanel">
    <select id="certificateSelect"></select>
    <button id="refreshButton" type="button">Refresh</button><br/><br/>
    <button id="signFileButton" type="button">Sign Dummy File</button>
</div>
<div id="dialog">
    <p id="dialogMessage"></p>
</div>
<div id="blockPanel">
</div>
#signatureControlsPanel {
    margin-top: 1em;
    display: none;
}
#blockPanel {
    display: none;
    padding: 0.5em;
}

External resources loaded into this fiddle: