Edit in JSFiddle

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

var app = angular.module('app', ['ui.bootstrap', 'blockUI']);

app.config(function(blockUIConfig) {
    blockUIConfig.autoInjectBodyBlock = false;
});

app.controller('ExampleController', function ($scope, $http, $modal, blockUI) {
    
    $scope.certificates = [];
    $scope.showSignatureControls = false;
    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=="
    });
    
    var onWebPkiError = function (message, error, origin) {
        blockUI.stop();
        log('Web PKI error originated at ' + origin + ': ' + error);
        showModal('Error', 'Web PKI error: ' + message);
    };

    var start = function () {
        blockUI.start('Detecting Web PKI ...');
        log('Checking component installation ...');
        pki.init({
            angularScope: $scope,
            defaultError: onWebPkiError,
            ready: onWebPkiReady,
            notInstalled: onWebPkiNotInstalled
        });
    };
    
    var onWebPkiNotInstalled = function (status, message) {
        log('Component not installed or outdated');
        blockUI.stop();
        showModal('Message', message + ' -- Click OK to go to installation page', function() {
            pki.redirectToInstallPage();
        });
    };
    
    var onWebPkiReady = function () {
        log('Component detected.');
        blockUI.message('Loading certificates ...');
        loadCertificates();
    };
    
    $scope.reloadCertificates = function() {
        blockUI.start('Loading certificates ...');
        loadCertificates();
    };
    
    var loadCertificates = function() {
        log('Listing certificates ...');
        pki.listCertificates().success(function (certs) {
            log('Certificates listed!');
            // we don't have to surround the following statement in a $scope.$apply(function() { ... })
            // block because we've passed our $scope to the pki object during the instantiation of the object
            $scope.certificates = certs;
            $scope.showSignatureControls = true;
            blockUI.stop();
        });
    };
    
    $scope.getCertificateDisplayName = function (cert) {
        return cert.subjectName + ' (issued by ' + cert.issuerName + ')';
    };

    // This function is called when the user clicks the button "Sign Dummy File"
    $scope.signFile = function () {
        blockUI.start('Signing ... (step 1/4)');
        // The first thing we'll do is read the certificate encoding
        log('Reading certificate ...');
        pki.readCertificate($scope.selectedCertificate.thumbprint).success(onReadCertificateCompleted);
    };
    
    // This function is the callback for when the readCertificate operation is completed
    var onReadCertificateCompleted = function (certContent) {
        blockUI.message('Signing ... (step 2/4)');
        // Now that we have acquired the certificate's encoding, we'll send that to the
        // server using Ajax
        log('Certificate binary encoding read, sending to server ...');
        $http.post('https://webpki.lacunasoftware.com/api/Signature/Start', {
            certificate: certContent
        }).success(onSignatureStartCompleted);
	};
    
    // This function is the callback for when the server replies back with the "to-sign-bytes"
    // and digest algorithm oid.
	var onSignatureStartCompleted = function (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;
        // Now that we have the bytes to be signed and the OID of the digest algorithm that
        // should be used during the signature, we call signData
		pki.signData({
			thumbprint: $scope.selectedCertificate.thumbprint,
			data: response.toSign,
			digestAlgorithm: response.digestAlgorithmOid
		}).success(onSignDataCompleted);
	};
    
    // This function is the callback for when the signData operation is completed
	var onSignDataCompleted = function (signature) {
        blockUI.message('Signing ... (step 4/4)');
        log('Signature completed, submitting to server ...');
        // We send the signature result back to the server, which will then use
        // its server-side SDK to assemble the signed PDF file
		$http.post('https://webpki.lacunasoftware.com/api/Signature/Complete', {
			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.
	var onSignatureCompleteCompleted = function () {
        log('Process completed!');
		blockUI.stop();
        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.close();
        });
	};
    
    // Auxiliary functions
    
    var log = function (message) {
        if (window.console) {
            window.console.log(message);
        }
    };
    
    var showModal = function (title, message, okCallback) {
        $modal.open({
            template: '<div class="modal-header"><h4 class="modal-title">{{title}}</h4></div><div class="modal-body">{{message}}</div><div class="modal-footer"><button class="btn btn-primary" ng-click="OK()">OK</button></div>',
            controller: 'ModalController',
            resolve: {
                message: function () { return message; },
                title: function () { return title; },
                okCallback: function () { return okCallback; }
            }
        });
    };
    
    // Once our controller is ready, we call the start method
    start();
});

app.controller('ModalController', function ($scope, $modalInstance, title, message, okCallback) {
    $scope.title = title;
    $scope.message = message;
    $scope.OK = function() {
        if (okCallback) {
            okCallback($modalInstance);
        } else {
            $modalInstance.close();
        }
    };
});
<div ng-app="app" block-ui="main" class="main">
    <div ng-controller="ExampleController">
        <form>
            <div id="signatureControlsPanel" ng-show="showSignatureControls">
                <p>
                    <select ng-model="selectedCertificate" ng-options="getCertificateDisplayName(cert) for cert in certificates">
                        <option value="">Choose a certificate ...</option>
                    </select>
                    <button type="button" ng-click="reloadCertificates()">Reload</button>
                </p>
                <p>
                    You will be signing <a href="https://webpki.lacunasoftware.com/Content/SampleDocument.pdf" target="_blank">this file</a>.
                </p>
                <p>
                    <button type="button" ng-click="signFile()">Sign File</button>
                </p>
            </div>
        </form>
    </div>
</div>
.main {
    min-height: 400px;
    padding: 1em;
}
#signatureControlsPanel {
    margin-top: 1em;
}