2

I created a custom button on a custom object that launches a Visualforce page to capture the signature of a user. The Visualforce page has two buttons: Capture Signature and Exit. Upon clicking Capture Signature, the canvas is captured and attached in the Notes and Attachments related list of the record. The problem I am facing is that my code is only working through desktop browsers and the Salesforce1 simulator (i.e. /one/one.app), but the attachment isn't getting attached when testing with my iPhone. On my iPhone, I am able to get to the Visualforce page, draw a signature, and click the buttons, however, the attachment isn't appearing in the Notes and Attachments related list. Here is my code:

Visualforce Page:

<apex:page docType="html-5.0" standardController="EHS_Procedure__c" extensions="ehsSignatureExtensionController">

<script>var $j = jQuery.noConflict();</script>
<apex:stylesheet value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.css')}"/>
<apex:includeScript value="{!URLFOR($Resource.jquery)}"  />
<apex:includeScript value="{!URLFOR($Resource.jquerymobile,'/jquerymobile/jquery.mobile-1.3.2.min.js')}"/>

<canvas id="signatureCanvas" width="315" height="400" style="border: 1px solid white;"/>  
<apex:includeScript value="/soap/ajax/28.0/connection.js"/>

<script>

sforce.connection.sessionId = "{!$Api.Session_Id}";
var canvas = document.getElementById("signatureCanvas");
var context = canvas.getContext("2d");
var mouseButton = 0;
var lastX = lastY = null;
var ehsId = '{!EHS_Procedure__c.Id}';

function saveSignature() {

    var image = canvas.toDataURL().split(',')[1];
    ehsSignatureExtensionController.saveSignature(ehsId,image,handleResult);
}

function handleResult(result,event) {
    if(result.success) {
        window.top.location.href='/'+ehsId;
    } else {
        alert('Error: '+result.errorMessage);
    }
}

function handleEvent(event) {
    if(event.type==="mousedown"||event.type==="touchstart") {
        mouseButton = event.which || 1;
        lastX = lastY = null;
    }
    if(event.type==="touchcancel" || event.type==="touchcancel" || event.type==="mouseup") {
        mouseButton = 0;
        lastX = lastY = null;
    }
    if((event.type==="touchmove" || event.type==="mousemove") && mouseButton) {
        var newX, newY;
        var canvasX = 0, canvasY = 0, obj = event.srcElement || event.target;
        do {
            canvasX += obj.offsetLeft;
            canvasY += obj.offsetTop;
        } while(obj = obj.offsetParent);
        if(event.targetTouches && event.targetTouches.length) {
            newX = event.targetTouches[0].clientX - (canvasX/2);
            newY = event.targetTouches[0].clientY - (canvasY/2);
        } else {
            newX = event.offsetX;
            newY = event.offsetY;
        }
        if(!lastX && !lastY) {
            lastX = newX;
            lastY = newY;
            context.beginPath();
            context.moveTo(lastX,lastY);
            context.lineTo(lastX,lastY,lastX,lastY);
            context.stroke();
        } else {
            context.beginPath();
            context.moveTo(lastX,lastY);
            context.lineTo(newX,newY);
            context.stroke();
            lastX = newX;
            lastY = newY;
        }
    }
    if(event.type=="touchmove" || event.type==="mousedrag" || (event.type==="selectstart" && (event.srcElement||event.target)===canvas)) {
        event.returnValue=false;
        event.stopPropagation();
        event.preventDefault();
        return false;
    }
}

canvas.addEventListener("mousedrag",handleEvent,true);
canvas.addEventListener("mousemove",handleEvent,true);
canvas.addEventListener("mousedown",handleEvent,true);
window.addEventListener("mouseup",handleEvent,true);
canvas.addEventListener("touchstart",handleEvent,true);
canvas.addEventListener("touchmove",handleEvent,true);
window.addEventListener("touchend",handleEvent,true);
window.addEventListener("selectstart",handleEvent,true);

</script>

<apex:form >
    <button onclick="saveSignature()">Capture Signature</button>
    <apex:commandButton action="{!cancel}" value="Exit"/>
</apex:form>

</apex:page>

Apex Class:

public with sharing class ehsSignatureExtensionController {

private final EHS_Procedure__c ehs;

public ehsSignatureExtensionController(ApexPages.StandardController controller) {
    ehs = (EHS_Procedure__c)controller.getRecord();
}

@RemoteAction public static RemoteSaveResult saveSignature(Id ehsId, String signatureBody) {
    Attachment a = new Attachment(ParentId=ehsId, name='Signature.png', ContentType='image/png', Body=EncodingUtil.base64Decode(signatureBody));
    Database.saveResult result = Database.insert(a,false);
    RemoteSaveResult newResult = new RemoteSaveResult();
    newResult.success = result.isSuccess();
    newResult.attachmentId = a.Id;
    newResult.errorMessage = result.isSuccess()?'':result.getErrors()[0].getMessage();
    return newResult;
}

public class RemoteSaveResult {
    public Boolean success;
    public Id attachmentId;
    public String errorMessage;
}

public pageReference cancel(){
    pageReference page = new PageReference('/'+ehs.id);
    page.setRedirect(true);
    return page;
}
}

Do you have any recommendations on getting this to work on the Salesforce1 app?

2

Take a look at the below url for salesforce1:
http://corycowgill.blogspot.in/2013/12/capturing-signatures-with-html5-canvas.html

The gist of it is to use an HTML 5 canvas with Javascript drawing, and then base64 encode the cavnas data so it can be sent as a string back to a custom controller. The controller then decodes the string and stores the resulting blob in the body of a document for example.

  • Thank you for responding. The example you posted is what I based my code on. The difference is that the code in the example queries for an Account instead of having a record Id passed. The code works perfectly through my desktop browser and the Salesforce1 simulator, but fails to create the attachment through the iOS Salesforce1 app. Any ideas to solve for this? – Tyler Sep 17 '14 at 20:26
1

Please check below post to create e-signature using HTML 5 canvas feature :

http://teach-force.blogspot.com/2014/02/capture-signature-on-ipad-using.html

1

The issue was with the custom button. I changed it to the below code and it now works:

<apex:commandButton value="Save Signature" onclick="saveSignature();return false;" styleClass="button"/>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.