Lightning Component for Dropbox

Hi All,

Today i will be showing you DropBox Lightning Component created by me and my colleague Balkishan Kachawa.

Dropbox is a file hosting service operated by Dropbox, Inc., headquartered in San Francisco, California,
that offers cloud storage, file synchronization, personal cloud, and client software. There are limits in storage of files in Salesforce. If you need a secure and free storage space for your files, you can use DropBox Lightning Component to store files directly in your DropBox app from Salesforce.

Features of this Lightning Component are :

  1. You can use this component on any sObject.
  2. You can store files for a specific record.
  3. You can upload multiple files.
  4. You can delete files directly in DropBox.
  5. You can view you files.

Click here to install Manage Package in your org.

After installing package register for My Domain.

Make sure you have DropBox Account. If you don’t have you can sign up and create DropBox App as below.

Sign up Dropbox account from DropBox website.

After the Sign up login into your dropbox account and then create a Dropbox App using following steps:

Go to on dropbox developer edition i.e. https://www.dropbox.com/developer
Click on My Apps > Create App.
Then fill all information about app and then click on create. See below screen shot.

dropbox

Manage Dropbox Key from Custom setting

Insert a record in custom setting using following steps:

  1. Navigate to Setup > Develop > Custom Settings, click on Manage of “Dropbox Key”.
  2. Click on New, than insert following value:

App Key : from DropBox App

App Secret : from DropBox App

Redirect URI : from salesforce <your domain>/apex/DropBoxOAuth or copy url from preview of DropBoxOAuth page.

isAuthentication : false

Click on Save.

Add Redirect URI in Dropbox App

To add Redirect URI, Open your Dropbox App and you must set auth2 Redirect URIs same as above Redirect URL.

That’s It.

Your final result will look like this:

EMI Calculator Component using Lightning

Hi All,

In this post I will tell you how to create EMI Calculator using Lightning Component.

How to Use EMI Calculator?

Our EMI Calculator is easy to use, intuitive to understand and is quick to perform. You can calculate EMI for home loan, car loan, personal loan, education loan or any other fully amortizing loan using this calculator.

Enter the following information in the EMI Calculator:

  • Principal loan amount you wish to avail (rupees)
  • Loan term (months or years)
  • Rate of interest (percentage)
  • EMI in advance OR EMI in arrears (for car loan only)

Let’s walk through code.

EMICalculator.cmp :

<aura:component implements="force:appHostable,force:hasRecordId,force:hasSObjectName,flexipage:availableForAllPageTypes">
    <ltng:require styles="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css"/>
    
    <div class="slds">
        <div class="slds-page-header">
            <div class="slds-grid">
                <div class="slds-col slds-has-flexi-truncate">
                    <div class="slds-media">
                        <div class="slds-media__figure">
                            <c:svgIcon svgPath="/resource/SLDS/assets/icons/standard-sprite/svg/symbols.svg#process" category="standard" size="large" name="user" />
                        </div>
                        <div class="slds-media__body">
                            <p class="slds-text-heading--label">Calculator</p>
                            <div class="slds-grid">
                                <h1 class="slds-text-heading--medium slds-m-right--small slds-truncate slds-align-middle">Calculate Your EMI</h1>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- /slds-col-->                        
            </div>   
            <!-- /slds-grid-->                 
        </div>
        <!-- /slds-page-header-->
        <div class="container">
            <div class="slds-grid slds-m-top--medium slds-wrap">
                <div class="slds-col--padded slds-size--1-of-1">
                    <div id="err" style="display:none;" class="slds-notify slds-notify--alert slds-theme--error slds-theme--alert-texture" role="alert">
                        <h2>Please fill all Information</h2>
                    </div>
                    
                    <div class="slds-form--stacked">
                        <div class="slds-form-element">
                            <label class="slds-form-element__label" >Loan Amount</label>
                            <div class="slds-form-element__control">
                                <input id="loanAmt" class="slds-input" type="text"  required="" />
                            </div>
                        </div>
                        <div class="slds-form-element">
                            <label class="slds-form-element__label" >Loan Tenure (Months)</label>
                            <div class="slds-form-element__control">
                                <input id="months" class="slds-input" type="text" required="" />
                            </div>
                        </div>
                        <div class="slds-form-element">
                            <label class="slds-form-element__label" >Interest Rate</label>
                            <div class="slds-form-element__control">
                                <input id="rate" class="slds-input" type="text" required="" />
                            </div>
                        </div>
                        <div class="slds-form-element slds-m-bottom--medium ">
                            <ui:button label="Submit" press="{!c.getEMIDetail}"/> &nbsp;
                            <ui:button label="Reset" press="{!c.reset}"/>   &nbsp;
                            <ui:button label="Monthly Detail" press="{!c.getEMIMonthly}"/><br/>                            
                        </div>                        
                    </div>
                </div>
                
                <div class="slds-col--padded slds-size--1-of-1 " >
                    <div id="emiDiv" style="display:none;">
                        <div class="slds-form-element">
                            <span class="slds-form-element__label">EMI</span>
                            <div class="slds-form-element__control">
                                <span class="slds-form-element__static"><div id="EMI"></div></span>
                            </div>
                        </div>
                        <div class="slds-form-element">
                            <span class="slds-form-element__label">Interest Payable</span>
                            <div class="slds-form-element__control">
                                <span  class="slds-form-element__static"><div id="interestP"></div></span>
                            </div>
                        </div>
                        <div class="slds-form-element">
                            <span class="slds-form-element__label">Total Payable</span>
                            <div class="slds-form-element__control">
                                <span  class="slds-form-element__static"><div id="totalP" ></div></span>
                            </div>
                        </div>
                    </div>
                    <div id="addchart" class="slds-scrollable--y" style="display:none; max-height: 280px;"></div>
                </div>                
            </div>
            
                        
        </div>        
    </div>    
</aura:component>

EMICalculatorController.js:

({
    getEMIDetail : function(component, event, helper) {
        helper.getEMI(component, "EMI");
    },
    getEMIMonthly : function(component, event, helper) {
        helper.getEMI(component, "Monthly");
    },
    reset : function(component, event, helper) {
        document.getElementById("emiDiv").style.display = "none";
        document.getElementById("addchart").style.display = "none";
        document.getElementById('loanAmt').value="";
        document.getElementById('months').value="";
        document.getElementById('rate').value="";
    },    

})

EMICalculatorHelper.js :

({
	getEMI : function(component, detail) {
        if(detail =="EMI"){
            document.getElementById("emiDiv").style.display = "block";
            document.getElementById("addchart").style.display = "none";
        }else if(detail =="Monthly"){
            document.getElementById("emiDiv").style.display = "none";
            document.getElementById("addchart").style.display = "block";
        }
		var loanAmt = document.getElementById('loanAmt').value;
        var months = document.getElementById('months').value;
        var rate = document.getElementById('rate').value;
        
        if (loanAmt == null || loanAmt.length == 0 || months == null || months.length == 0 || rate == null || rate.length == 0) {
            document.getElementById("err").style.display = "block";            
        } else {
            document.getElementById("err").style.display = "none";                           
            var rate1 = rate / 1200;
            var emi= loanAmt * rate1 / (1 - (Math.pow(1 / (1 + rate1), months)));//Math.round(loanAmt * rate1 / (1 - (Math.pow(1 / (1 + rate1), months))) * 100) / 100;
            document.getElementById('EMI').innerHTML = Math.round(emi);
            document.getElementById('interestP').innerHTML = Math.round(emi * months) ;//Math.round((emi * months)) ;
            document.getElementById('totalP').innerHTML = Math.round((document.getElementById('interestP').innerHTML) * 1 - loanAmt * 1);//Math.round(((document.getElementById('interestP').innerHTML) * 1 - loanAmt * 1) * 100) / 100;
            
            var tile='<ul class="slds-list--vertical slds-has-cards">';
            var balance=0;
            for(i=1; i<=months; i++){                    
                if(i==1){
                    balance = loanAmt;                       
                }                       
                var interest = balance* (rate/100.0)/12;//(Math.round((balance* (rate/100.0)/12)*100)/100).toFixed(2);
                var Principal = emi - interest;//(Math.round((emi - interest)*100)/100).toFixed(2);
                balance = balance - Principal;//(Math.round((balance - Principal)*100)/100).toFixed(2);
                
                tile += '<li class="slds-list__item">';
                tile += '<div class="slds-tile slds-tile--board">';
                tile += '<p class="slds-tile__title slds-truncate"><a href="#">Month - '+ i +' </a></p>';
                tile += '<div class="slds-tile__detail">';
                tile += '<p class="slds-text-heading--medium">Installment - '+ Math.round(emi) +'</p>';
                tile += '<p class="slds-truncate"><a href="#">Interest - '+ Math.round(interest) +'</a></p>';
                tile += '<p class="slds-truncate">Princple - '+ Math.round(Principal) +'</p>';
                tile += '<p class="slds-truncate">Balance - '+ Math.round(balance) +'</p>';
                tile += '</div>';
                tile += '</div>';
                tile += '</li>';
            }
            tile += '</ul>';
            document.getElementById("addchart").innerHTML = tile;            
        }	
	}
})

EMICalculator.css

.THIS .slds-list__item{
    width: 300px;
    float: left;
    margin: 4px!important;
}

Your final result will look like this.

Thanks

How to use Nested Components in Lightning Component Using Salesforce Lightning Design System

Hi Guys,

In my last post I showed how to use SVG Icon in Lightning Component. In this post, I will be showing you how to build a Nested component in Lightning Component using Salesforce Lightning Design System. In this you can see Tree view of Accounts and its related contacts like:

Screenshot_2015-11-04-20-23-16

Screenshot_2015-11-04-20-23-30
Let’s walk through code by few steps:

Screenshot_2015-11-04-20-22-58

Step-1: AccConListController.apxc

public class AccConListController {
    @AuraEnabled
    public static List<Account> getAccounts() {
        List<Account> accounts=[SELECT Id, Name, (select name, Phone, Email FROM Contacts) FROM Account limit 1000];
        return accounts;
    }
}

In this class we create a funtion which is used for getting accounts and its related contacts.

Step-2: AccountRow.cmp

<aura:component >
    <aura:attribute name="acc" type="Account" />
    <aura:attribute name="ext" type ="String" default="plus"/>
    <li  id="tree0-node0" class="slds-tree__branch slds-is-open" role="treeitem" aria-level="1" aria-expanded="true">
        <div class="slds-tree__item">
            <aura:if isTrue="{!v.acc.Contacts[0] != null}">
                <aura:if isTrue="{!v.ext=='plus'}">
                    <div id="plus" >➕</div>
                    <aura:set attribute="else">
                        <div id="minus">➖</div>
                    </aura:set>
                </aura:if> 
                &nbsp;
                <aura:set attribute="else">
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                </aura:set>
            </aura:if> 
            <a id="tree0-node0-0-link"  tabindex="-1" onclick="{!c.showHidePanel}" role="presentation">{!v.acc.Name}</a>
        </div>
        
        <ul aura:id="{!v.acc.Id}" id="{!v.acc.Id}" style="display:none;" class="slds-tree__group slds-nested" role="group" aria-labelledby="tree0-node0-link">
            <aura:iteration items="{!v.acc.Contacts}" var="con">
                <li id="tree0-node0-1" class="slds-tree__item" role="treeitem" aria-level="2" style="margin-left: 20px;">
                    <a href="#" role="presentation" class="slds-truncate" style="color: darkgoldenrod;">{!con.Name}</a>    	
                </li>
            </aura:iteration>
        </ul>
    </li>
</aura:component>

This is a Child component and it is used for show an account name and its related contacts.

Step-3: AccountRowController.js

({
	showHidePanel : function(component, event, helper) {
        var id=component.get("v.acc.Id");        
        var e=document.getElementById(id);      
        if (e.style.display == 'block' || e.style.display==''){
            e.style.display = 'none';
            component.set("v.ext","plus");
        }else{
            e.style.display = 'block';
            component.set("v.ext","minus");
        } 
	},
})

This is controller of AccountRow Component.

Step-4: AccountTree.cmp

<aura:component controller="AccConListController" implements="force:appHostable">
    <ltng:require styles="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css" 
                  scripts="/resource/jquerymin" 
                  afterScriptsLoaded="{!c.doInit}" />    
    <aura:attribute name="Accounts" type="Account[]" />
    <div class="slds">
        <div class="slds-page-header">
            <div class="slds-grid">
                <div class="slds-col slds-has-flexi-truncate">
                    <div class="slds-media">
                        <div class="slds-media__figure">
                            <c:svgIcon svgPath="/resource/SLDS/assets/icons/standard-sprite/svg/symbols.svg#process" category="standard" size="large" name="user" />
                        </div>
                        <div class="slds-media__body">
                            <p class="slds-text-heading--label">Tree View</p>
                            <div class="slds-grid">
                                <h1 class="slds-text-heading--medium slds-m-right--small slds-truncate slds-align-middle">Account -> Contact</h1>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- /slds-col-->                        
            </div>   
            <!-- /slds-grid-->                 
        </div>
        <!-- /slds-page-header-->
        <div class="slds-tree-container" role="application">
            <ul class="slds-tree" role="tree" aria-labelledby="treeheading" aria-activedescendant="tree0-node0">
                <aura:iteration items="{!v.Accounts}" var="acc">        	
                    <c:AccountRow acc="{!acc}" />
                </aura:iteration>
            </ul>
        </div>
    </div>
</aura:component>

This is parent component that holds AccountRow component as a nested component. And also i am using here SVG Icon in header. For more detail about SVG Icon see in my previous post or click here.

Step-5: AccountTreeController.js

({
	doInit : function(component, event, helper) {          
        helper.getAccounts(component);          
    },
    
    showPanel : function(component, event, helper){        
        helper.onLoadPage(component); 
	},
    
})

This is controller of AccountTree Component.

Step-6: AccountTreeHelper.js

({
	//Fetch the Accounts from the Apex controller
    getAccounts: function(component) {        
        var action = component.get("c.getAccounts");
        //Set up the callback
        var self = this;
        action.setCallback(this, function(actionResult) {
            component.set("v.Accounts", actionResult.getReturnValue());            
        });        
        $A.enqueueAction(action);                
    },        
})

This is helper of AccountTree Component. Its getAccounts() function calls getAccounts() method of AccConListController.apxc class

How to use SVG Icon in Lightning Component Using Salesforce Lightning Design System

Step 1: Create the Lightning Component

Log into your org, and open the Developer Console. Create a new Lightning component from the menu: File > New > Lightning Component

Name your component: svgIcon

Step 2: Write code in svgIcon.cmp using Component tab

<aura:component>
	<aura:attribute name="svgPath" default="" type="String" description="the path for the icon in the static resource, this will be use in a SVG use tag" />
	<aura:attribute name="name" default="" type="String" description="Symbol name of icon" />
	<aura:attribute name="class" default="" type="String" description="the class of this SVG tag, can be use for CSS purpose" />
	<aura:attribute name="containerClass" default="" type="String" description="Container class name for span container of icon" />
	<aura:attribute name="category" default="" type="String" description="Category of icon- action, standard, utility etc." />
	<aura:attribute name="size" default="" type="String" description="Size of icon-- small, medium, large" />
	<aura:attribute name="assistiveText" default="" type="String" description="Description name of icon" />
	<span aura:id="container" class="{!v.containerClass}">
		<span aura:id="assistiveText" class="slds-assistive-text">{!v.assistiveText}</span>
	</span>
</aura:component>

Step 3: Write code in svgIconHelper.js using Helper tab

({
	renderIcon: function(component) {
		var prefix = "slds-";
		var svgns = "http://www.w3.org/2000/svg";
		var xlinkns = "http://www.w3.org/1999/xlink";
		var size = component.get("v.size");
		var name = component.get("v.name");
		var classname = component.get("v.class");
		var category = component.get("v.category");

		var containerClassName = [
			prefix+"icon__container",
			prefix+"icon-"+category+"-"+name,
			classname
		].join(' ');
		var iconClassName = prefix+"icon "+prefix+"icon--" + size;
		component.set("v.containerClass", containerClassName);

		var svgroot = document.createElementNS(svgns, "svg");
		svgroot.setAttribute("aria-hidden", "true");
		svgroot.setAttribute("class", iconClassName);
		svgroot.setAttribute("name", name);

		// Add an "href" attribute (using the "xlink" namespace)
		var shape = document.createElementNS(svgns, "use");
		shape.setAttributeNS(xlinkns, "href", component.get("v.svgPath"));
		svgroot.appendChild(shape);

		var container = component.find("container").getElement();
		container.insertBefore(svgroot, container.firstChild);
	}
})

Step 4: Write code in svgIconRenderer.js using Renderer tab

({
	render: function(component, helper) {
		// By default, after the component finished loading data/handling events,
		// it will call this render function this.superRender() will call the
		// render function in the parent component.
		var ret = this.superRender();

		// Calls the helper function to append the SVG icon
		helper.renderIcon(component);
		return ret;
	}
})

Step 5: Use the New Component

Now we create new Lightning Component and paste svg component like as below image:

svgicon2

And Now write below code in component:

<aura:component>
    <ltng:require styles="/resource/SLDS/assets/styles/salesforce-lightning-design-system-vf.css"/>
    <div class="slds">
        <div class="slds-page-header">
            <div class="slds-grid">
                <div class="slds-col slds-has-flexi-truncate">
                    <div class="slds-media">
                        <div class="slds-media__figure">
                            <c:svgIcon svgPath="/resource/SLDS/assets/icons/standard-sprite/svg/symbols.svg#process" category="standard" size="large" name="user" />
                        </div>
                        <div class="slds-media__body">
                            <p class="slds-text-heading--label">SVG Icon</p>
                            <div class="slds-grid">
                                <h1 class="slds-text-heading--medium slds-m-right--small slds-truncate slds-align-middle">Set your SVG</h1>
                            </div>
                        </div>
                    </div>
                </div>
                <!-- /slds-col-->                        
            </div>   
            <!-- /slds-grid-->                 
        </div>
        <!-- /slds-page-header-->
	</div>    
	<!-- /slds-->
</aura:component>

After the above step, now its time to show preview using Application and this preview is viewing like below image:

svgicon

Note: Here Static Resource is named SLDS.

Thanks.

Create e-Signature with Salesforce Lightning Design System

Hi All,
In my previous post I have shown you how we can Meta data Api using Oauth 2.0 workflow.
Today I will tell you how we can use canvas to draw your signature and how we can attach this signature with your information in Salesforce lightning Design System.

When insert new contact it will look like this :
new

And when update existing contact it will look like this (using contact id in url with conId parameter):
update

Let’s walk through code:

Create ContactWithSignatureController class:

global with sharing class ContactWithSignatureController {
    public contact con {get;set;}
    public boolean flag {get;set;}
    public string attId {get;set;}
    public ContactWithSignatureController() {
        String conId = apexPages.CurrentPage().getParameters().get('conId');
        con = new contact();
        flag = true;
        attId = '';
        if (conId != null && conId.trim() != '') {
            con = [select id, firstname, lastname, name, phone from contact where id = : conId];
            flag = false;
            list < attachment > attIds = [select id from Attachment where name = 'Signature Image'
                and parentId = : conId
            ];
            if (attIds.size() > 0) {
                attId = attIds[0].id;
            }
        }
    }
    public void saveCon() {
        upsert con;
    }

    @RemoteAction
    global static String saveSignature(String imageUrl, String pId) {
        try {
            delete[select id from Attachment where name = 'Signature Image'
                and parentId = : pId];
            Attachment accSign = new Attachment();
            accSign.ParentID = pId;
            accSign.Body = EncodingUtil.base64Decode(imageUrl);
            accSign.contentType = 'image/png';
            accSign.Name = 'Signature Image';
            accSign.OwnerId = UserInfo.getUserId();
            insert accSign;
            return 'success';

        } catch (Exception e) {
            system.debug('---------- ' + e.getMessage());
            return JSON.serialize(e.getMessage());
        }
        return null;
    }
}

Create page with “ContactWithSignature” name

<apex:page id="pg" controller="ContactWithSignatureController" showHeader="false" sidebar="false" standardStylesheets="false">
    <html xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">

    <head>
        <apex:stylesheet value="{!URLFOR($Resource.SLDS080, 'assets/styles/salesforce-lightning-design-system-vf.css')}" />
        <STYLE TYPE="text/css">
            ::-webkit-scrollbar {
                width: 8px;
                height: 8px;
            }
            
            ::-webkit-scrollbar-track-piece {
                background-color: #a8b7c7;
                border-radius: 20px;
            }
            
            ::-webkit-scrollbar-thumb:vertical {
                height: 30px;
                background-color: #e0e5ee;
                border-radius: 20px;
            }
        </STYLE>

    </head>
    <apex:form id="mainForm">
        <apex:outputPanel id="rnd">
            <script>
                function SaveSign() {
                    window.frames[0].frameElement.contentWindow.saveSignature("{!con.id}");
                }
            </script>
        </apex:outputPanel>

        <apex:actionFunction action="{!saveCon}" name="saveCon" reRender="rnd" oncomplete="SaveSign();return false;" />
        <div class="slds">
            <div class="slds-page-header">
                <div class="slds-grid">
                    <div class="slds-col slds-has-flexi-truncate">
                        <div class="slds-media">
                            <div class="slds-media__figure">
                                <svg aria-hidden="true" class="slds-icon slds-icon--large slds-icon-standard-user">
                                    <use xlink:href="{!URLFOR($Resource.SLDS080, 'assets/icons/standard-sprite/svg/symbols.svg#contact')}"></use>
                                </svg>
                            </div>
                            <div class="slds-media__body">
                                <p class="slds-text-heading--label">Contact</p>
                                <div class="slds-grid">
                                    <h1 class="slds-text-heading--medium slds-m-right--small slds-truncate slds-align-middle">
                                        <apex:outputPanel rendered="{!flag}">
                                            New Contact
                                        </apex:outputPanel>
                                        <apex:outputPanel rendered="{!!flag}">
                                            Update Contact
                                        </apex:outputPanel>
                                    </h1>
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- /slds-col-->
                </div>
                <!-- /slds-grid-->
            </div>
            <!-- /slds-page-header-->
            <div class="container">
                <div class="slds-form--horizontal slds-m-right--xx-large slds-m-top--xx-large slds-p-right--xx-large">
                    <div class="slds-form-element">
                        <label class="slds-form-element__label" for="sample1">First Name</label>
                        <div class="slds-form-element__control">
                            <apex:inputField value="{!con.firstname}" styleClass="slds-input" html-placeholder="First Name" />
                        </div>
                    </div>
                    <div class="slds-form-element">
                        <label class="slds-form-element__label" for="sample1">Last Name</label>
                        <div class="slds-form-element__control">
                            <apex:inputField value="{!con.lastname}" styleClass="slds-input" html-placeholder="Last Name" />
                        </div>
                    </div>
                    <div class="slds-form-element">
                        <label class="slds-form-element__label" for="sample1">Phone</label>
                        <div class="slds-form-element__control">
                            <apex:inputField value="{!con.phone}" styleClass="slds-input" html-placeholder="Phone" />
                        </div>
                    </div>
                    <div class="slds-form-element">
                        <span class="slds-form-element__label">Signature </span>
                        <div class="slds-form-element__control">
                            <iframe src="/apex/ContactWithSignatureComponent?conId={!con.id}" style="border:none; width:360px; height:125px"></iframe>
                        </div>
                        <apex:outputPanel rendered="{!if(!flag && attId!='',true,false)}">
                            <br/>
                            <span class="slds-form-element__label">Current Signature </span>
                            <div class="slds-form-element__control">
                                <apex:image url="/servlet/servlet.FileDownload?file={!attId}" />
                            </div>
                        </apex:outputPanel>
                    </div>
                    <div class="slds-form-element">
                        <div class="slds-button-group slds-float--right" role="group">
                            <apex:commandButton value="Submit" onclick="saveCon();return false;" styleClass="slds-button slds-button--neutral" />
                            <apex:commandButton value="Clear" onclick="window.frames[0].frameElement.contentWindow.clearSign();return false;" styleClass="slds-button slds-button--neutral" />
                        </div>
                    </div>
                </div>
            </div>
			<!-- /container-->
		</div>
    </apex:form>

    </html>
</apex:page>

Create another page with “ContactWithSignatureComponent” name

<apex:page controller="ContactWithSignatureController" standardStylesheets="false" sidebar="false" showHeader="false">
    <apex:includeScript value="/soap/ajax/28.0/connection.js" />
    <apex:form id="pbform">
        <div>
            <canvas id="signatureCanvas" height="100px" width="350px" style="    border: 1px solid #d8dde6; border-radius: 8px;"></canvas>
        </div>
    </apex:form>
    <script>
        var canvas;
        var context;
        var drawingUtil;
        var isDrawing = false;
        var pId = '';
        var prevX, prevY, currX, currY = 0;
        var pId;

        function DrawingUtil() {
            isDrawing = false;
            canvas.addEventListener("mousedown", start, false);
            canvas.addEventListener("mousemove", draw, false);
            canvas.addEventListener("mouseup", stop, false);
            canvas.addEventListener("mouseout", stop, false);
            canvas.addEventListener("touchstart", start, false);
            canvas.addEventListener("touchmove", draw, false);
            canvas.addEventListener("touchend", stop, false);
            w = canvas.width;
            h = canvas.height;
        }

        function start(event) {
            event.preventDefault();

            isDrawing = true;
            prevX = currX;
            prevX = currY;
            currX = event.clientX - canvas.offsetLeft;
            currY = event.clientY - canvas.offsetTop;

            context.beginPath();
            context.fillStyle = "cadetblue";
            context.fillRect(currX, currY, 2, 2);
            context.closePath();

        }

        function draw(event) {
            event.preventDefault();
            if (isDrawing) {
                prevX = currX;
                prevY = currY;
                currX = event.clientX - canvas.offsetLeft;
                currY = event.clientY - canvas.offsetTop;
                context.beginPath();
                context.moveTo(prevX, prevY);
                context.lineTo(currX, currY);
                context.strokeStyle = "cadetblue";
                context.lineWidth = "2";
                context.stroke();
                context.closePath();
            }
        }

        function stop(event) {
            if (isDrawing) {
                context.stroke();
                context.closePath();
                isDrawing = false;
            }
        }

        function clearSign() {
            context.clearRect(0, 0, w, h);
        }

        canvas = document.getElementById("signatureCanvas");
        context = canvas.getContext("2d");
        context.strokeStyle = "black";
        context.lineWidth = "2";
        drawingUtil = new DrawingUtil(canvas);

        function saveSignature(conId) {
            var strDataURI = canvas.toDataURL();
            strDataURI = strDataURI.replace(/^data:image\/(png|jpg);base64,/, "");
            pId = conId;
            var result = ContactWithSignatureController.saveSignature(strDataURI, conId, processResult);

        }

        function processResult(result) {
            window.parent.location.href = '/apex/ContactWithSignature?conId=' + pId;
        }
    </script>
</apex:page>

Now its time to preview the ContactWithSignature page and fill contact information with e-Signature. And When you click on “Submit” button it will redirect to detail page of contact.

For more information mail me on this Email Address: sushil.verma1988@gmail.com

Thanks