Best Practices from Oracle Development's A‑Team

Capturing Signatures in MAF Applications

Jeevan Joseph
Principal Solutions Engineer


We recently worked with a customer who had implemented a workflow process in a MAF application. The final step of this workflow process was to request the user to sign the application on the mobile device using the user’s finger before submitting it. The AMX component set does not have a built-in signature capture component, but with the power of custom components in AMX, we were able to build a signature capture component in just a couple of hours. This article walks through how we built this functionality with just pure HTML5, JavaScript and CSS.

Screen Shot 2015-01-21 at 4.29.41 PM
In this article, we implemeted our own code to capture touch events and convert them to lines, strokes and curves on the HTML 5 Canvas. There are however many other ways to capture the touch events and draw strokes on the canvas including leveraging jQuery plugins. However you decide to capture the strokes, this post helps you package this functionality in to a reusable custom component.

Main Article

Our final custom component markup will look like this :

<ateam:signature id="container"/> 

Using a custom component, we shrunk down the whole signature capture “feature” in to a simple and elegant tag.

A custom component consists of pure JavaScript and some optional CSS. Please take a look at my previous post if you need a quick primer on custom components. The Javascript generates the DOM elements and attaches call back functions to these DOM elements where required to fulfill the requirements of the behavior we are trying to implement. For the signature capture, we will implement it leveraging the canvas element in HTML 5. Then we shall use Javascript to track the touch events on the device and draw strokes and curves on the Canvas to match the touch events. The JavaScript for the custom component's render function is shown below:

(function () {     signatureCap.prototype.render = function (amxNode, id) {         try {             var container = document.createElement("div");             container.id = id;             container.width = "100%";             var canvas = document.createElement("canvas");             canvas.id = "signature";             canvas.className = "signpad";             container.appendChild(canvas);             var clearCanvasButton = document.createElement("div");             clearCanvasButton.id = id + "_ClearButton";             clearCanvasButton.textContent = "clear";             clearCanvasButton.className="reject";             container.appendChild(clearCanvasButton);             var getSignatureButton = document.createElement("div");             getSignatureButton.id = id + "_getSigButton";             getSignatureButton.textContent = "Accept";             getSignatureButton.className="accept";             container.appendChild(getSignatureButton);             adf.mf.api.amx.addBubbleEventListener(clearCanvasButton, "tap", this._handleClearButton);             adf.mf.api.amx.addBubbleEventListener(getSignatureButton, "tap", this._handleGetSignatureButton);         }         catch (problem) {             adf.mf.log.Framework.logp(adf.mf.log.level.SEVERE, "signature", "render", "Problem with custom component creation: " + problem);         }         return container;     }; 

It setups the DOM elements for capturing the signature, including the canvas, and buttons to clear and store the canvas data.
The adf.mf.api.amx.addBubbleEventListener api attaches functions that need to get invoked when the buttons are pressed. These functions extract or clear the canvas data. Its important to note the post display function here :

var createPad = function(){                     sigCapture = new SignatureCapture("signature");             }; signatureCap.prototype.postDisplay = function (event) {         try {             window.setTimeout(createPad,250);         }         catch (problem) {             adf.mf.log.Framework.logp(adf.mf.log.level.SEVERE, "exampleEvents", "_handleBubbleEvent", "Problem in exampleEvents.prototype._handleBubbleEvent: " + problem);         }     }; 

The post display function uses a timeout to initialize the canvas, since MAF today does not have an event that gets triggered when the page rendering is complete. These are the vital parts of the solutions apart from the code to capture strokes on the canvas, and as previously mentioned, the actual painting can be captured in a lot of different ways, including leveraging jQuery plugins . The full source can be seen in the accompanying sample application.

Extracting Canvas Data

Once we capture the signature, we ned to extract the data from the canvas so that we can store it either on the device, or as in the case of our customer, send it to a server to be stored in a database so that it can be re-generated on mobile applications or even web applications.
We use the canvas’ toDataURL() function to get the signature data in text form. This is sent to a server using a REST API exposed by the server and stored in a DB. The signature and can be rendered visually again from the data by setting this as the source of an image tag. This makes it trivial to re-render the signature in a web app, mobile app, or any channel that uses HTML. In the example application, we have a image element right below the capture area that re-renders the signature from the captured data.

var dataString = this.canvas.get(0).toDataURL("image/png"); $("#renderArea").fadeOut(); $("#renderArea").delay(400).attr('src',dataString).fadeIn(); 

The full sample application cam be downloaded here.

Be the first to comment

Comments ( 0 )
Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.Captcha