We tried to integrate the multiple signature to VF page, but we have some issue when we scroll the page for signature, the signature part not working properly. Can anyone please help me out in this?

    <style type="text/css">
        @page { size: 8.27in 11.69in; /* A4 width and height */ };
    <apex:stylesheet value="//code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
    <apex:includeScript value="//code.jquery.com/jquery-2.1.1.min.js" />
    <apex:includeScript value="//code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js" />
    <script>var $j = jQuery.noConflict();</script>
    <apex:form >
        <apex:pageMessages />

        <apex:pageBlock rendered="{!NOT(enableSFStd)}">  
            <div style="width:100%;" >
                <div style="width:80%; margin:auto; border: 0px solid red">
                    <div id="header" style="height:30px;border: 0px solid blue">

                    <div id="body" >
                        <div id="personaldetailsection">
                           <!-- <div style="height:30px;border: 0px solid blue ;">
                                <span style="float:right"><b>PERSONAL DETAILS</b></span>

                                    <div style="height:30px; border: 0px solid blue;">
                                        <span>Applicant Signature</span>
                                    <div style="height:30px; border: 0px solid blue;">
                                        <span>Applicant Signature</span>
                                    <div style="height:30px; border: 0px solid blue;">
                                        <span>Applicant Signature</span>
                                    <div style="height:30px; border: 0px solid blue;">
                                        <span>Applicant Signature</span>
                                    </div><div style="height:300px; border: 0px solid blue;">
                                        <span>Applicant Signature</span>

                                    <!---------------Signature Section Starts ---------->
                                    <div style="padding-bottom: 10px; border: 0px solid blue;position:absolute;">                     

                                        <div id="signatureCaptureHome"  style="margin:0px 0 0 20px; " > 
                                            <div id="content">
                                                <apex:outputPanel rendered="{!signId == null}">
                                                    <canvas class="canvasElement" id="signatureCanvas" width="285" height="85"

style= "border:2px solid #000" />

                    <div id="footer"></div>
            <apex:actionFunction action="{!savePDF}" name="savePDF"/>

    <apex:includeScript value="/soap/ajax/28.0/connection.js"/>         
    <script type="text/javascript">
        sforce.connection.sessionId = "{!$Api.Session_Id}";

        var isDrawing = false;
        var accountId = '';       

        function DrawingUtil(canvas) 
            console.log("Inside DrawingUtil"+canvas);
            isDrawing = false;

        //Start Event for Signature Capture on HTML5 Canvas
        function start(event) 
            console.log("Inside Start Event");
            isDrawing = true;
            canvas = document.getElementById(this.id);
            context = canvas.getContext("2d");    
            context.strokeStyle = "rgb(155,0,0,0.5)";      
            context.moveTo(event.pageX - canvas.getBoundingClientRect().left,event.pageY -

canvas.getBoundingClientRect().top); //context.moveTo(event.touches[0].pageX - canvas.getBoundingClientRect().left,event.touches[0].pageY - canvas.getBoundingClientRect().top); } //Event while someone is drawing to Capture the path while they draw.... function draw(event) { event.preventDefault(); console.log("Inside draw Event");

            if(isDrawing) {     
                //context.lineTo(event.touches[0].pageX - canvas.getBoundingClientRect().left,event.touches[0].pageY -

canvas.getBoundingClientRect().top); context.lineTo(event.pageX - canvas.getBoundingClientRect().left,event.pageY - canvas.getBoundingClientRect().top); context.stroke(); } }

        //Event when someone stops drawing their signature line
        function stop(event) {
            console.log("Inside stop Event");
            if(isDrawing) {

              isDrawing = false;  


        var canvasCollection = [];
        var canvas = [];
        var context = [];
        var drawingUtil = [];
        canvasCollection = getElementsByClassName('canvasElement');
        var canvasLength = canvasCollection.length;
        for(var j=0;j<canvasLength;j++)  { 
            canvas[j] = document.getElementById(canvasCollection[j].id);
            context[j] = canvas[j].getContext("2d");
            context[j].strokeStyle = "#4105F4";   
            drawingUtil[j] = new DrawingUtil(canvas[j]);

        function CaptureSignature()
            var canvasNames = [];
            canvasNames = getElementsByClassName('canvasElement');
            var length = canvasNames.length;
            for(var j=0;j<length ;j++)  { 
                var canvas = document.getElementById(canvasNames[j].id);
                var strDataURI = canvas.toDataURL();
                strDataURI = strDataURI.replace(/^data:image\/(png|jpg);base64,/, "");

        function processResult(result)


global with Sharing Class CustomerSignupform
    public String rendermode { get; set; }
    public String recordId { get; set; }
    public String signId;    
    public Boolean enableSFStd { get; set; }    
    private Lead currentLead = new Lead();
    private Apexpages.StandardController controller;

    static final String SIGN_IMG_NAME = 'Sign.png';
    static final String PDF_NAME = 'SignForm.pdf';

    //Constructor Validate when page loads
    public CustomerSignuporm(Apexpages.StandardController stdCon) {
        controller = stdCon;
        enableSFStd = false;

    //Validate the page whether it has Lead Id or not
    //And also validate whether the signup form is already signed or not
    private Boolean validatePage() {
        // Check page has id parameters or not
        if (Apexpages.CurrentPage().getParameters().get('id') == null || Apexpages.CurrentPage().getParameters().get('id') == '') {
            ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.WARNING,'Please select an Lead.');
            enableSFStd = true;
            return true;
        recordId = Apexpages.CurrentPage().getParameters().get('id');

        //Check it is a valid Lead or not
        list<Lead> lstLead = [Select id,Name from Lead WHERE id =:recordID];
        if (lstLead.size() > 0) {             
            currentLead = lstLead[0];
        else {
            ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.ERROR,'Customer not available');
            recordID = null;
            enableSFStd = true;

        //Set render mode to pdf if query string contains renderpdf
        if (Apexpages.CurrentPage().getParameters().get('renderpdf') != null) {
            rendermode = 'pdf';
        return false;
     public Void getLeadDetails()
        Lead leaddetails = new Lead();
         User Owner = new User();
        recordID = ApexPages.CurrentPage().getparameters().get('id');
        leaddetails = [SELECT id,SAP_Customer__c,OwnerId,NSL_Number__c
                FROM Lead WHERE id =:recordID];
                        /*****for email***************/        
        OwnerID = leaddetails.OwnerId;
        NslCustomer = leaddetails.NSL_Number__c; 
        Owner = [SELECT id, name, email FROM User WHERE id =:OwnerID];   
        email = Owner.Email;
        SalesExecutive = Owner.name;

    //Remote Action to generate Signature as Attachment
    global static String Signature(String signatureBody, String parentId,String signName) {
        try {
            //Delete Signature if already present

            //Create New attachment for the Signature
            Attachment a = new Attachment();
            a.ParentId = parentId;
            a.Body = EncodingUtil.base64Decode(signatureBody);
            a.ContentType = 'image/png';
            a.Name = signName;
            insert a;
        catch(Exception e) {
            system.debug('Create Signature Exception:' + e);
            //return JSON.serialize(e);
        return null;

    //After creating signature need to create PDF file for Customer Signup
    public PageReference savePDF() {

        PageReference pdf = Page.CustomerSignupform;
        pdf.getParameters().put('renderpdf', 'true');

        Boolean pdfGenerated = false;

        // create the PDF new attachment
        Attachment attach = new Attachment();
        Blob body;
        try {
            // returns the output of the page as a PDF
            body = pdf.getContentAsPDF();
            pdfGenerated = true;
        catch (Exception e) {
            body = Blob.valueOf('PDF generation failed');

        attach.Body = body;
        attach.Name = ''+ NslCustomer+'_'+ DateTime.Now()+'.pdf'; // add the user entered name
        attach.IsPrivate = false;
        attach.ParentId = recordID;// attach the pdf to the Lead

        list<Lead> lstLead = [Select id from Lead WHERE id =:recordID];
        if (lstLead.size() > 0) {
            insert attach;

    // send the user to the account to view results
            pdfGenerated = (pdfGenerated || Test.isRunningtest());
            if (pdfGenerated) {
                //Update Lead Record
                currentLead = lstLead[0];
                currentLead.Email_Complete__c = true;
                //currentLead.Signup_Form_Complete__c = true;
                update currentLead;

        // send the user to the Lead to view results
        return new PageReference('/'+recordID);


    //Delete Signature from Attachment if it is present
    private static void deleteSignature(String parentId) {
        List<Attachment> lstAtch=[SELECT Id 
                                    FROM Attachment 
                                    WHERE Name=:SIGN_IMG_NAME 
                                        AND ParentId=:parentId
                                    LIMIT 1000];
            delete lstAtch;

    //Returns Signature from Attachment if available
    public String getSignId() {
        List<Attachment> lst=[SELECT Id,Name,ParentId 
                                FROM Attachment 
                                WHERE Name=:SIGN_IMG_NAME 
                                    AND ParentId=:recordId];
        if(lst.size()>0) {
        else {
        return signId;


1 Answer 1


Looks like in your java script function Start and Draw, the mouse event capture uses page position (pageX and pageY). When you capture signature you need to capture mouse position based on element.

Change the below code lines

context.lineTo(event.pageX - canvas.getBoundingClientRect().left,event.pageY - canvas.getBoundingClientRect().top);


context.lineTo(event.clientX - canvas.getBoundingClientRect().left,event.clientX - canvas.getBoundingClientRect().top);

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .